PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

स्प्रिंगबूट+कोटलिन+पोस्टग्रेज और JSONB:org.hibernate.MappingException:JDBC प्रकार के लिए कोई बोली मैपिंग नहीं

मैं पुल-अनुरोध में अपना समाधान प्रस्तावित करता हूं

इकाई को इसमें बदलने का विचार है:

import com.example.demo.pojo.SamplePojo
import com.vladmihalcea.hibernate.type.json.JsonBinaryType
import com.vladmihalcea.hibernate.type.json.JsonStringType
import org.hibernate.annotations.Type
import org.hibernate.annotations.TypeDef
import org.hibernate.annotations.TypeDefs
import javax.persistence.*

@Entity
@Table(name = "tests")
@TypeDefs(
        TypeDef(name = "json", typeClass = JsonStringType::class),
        TypeDef(name = "jsonb", typeClass = JsonBinaryType::class)
)
data class SampleEntity (
    @Id @GeneratedValue
    val id: Long?,
    val name: String?,

    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    var data: Map<String, Any>?
) {

    /**
     * Dependently on use-case this can be done differently:
     * https://stackoverflow.com/questions/37873995/how-to-create-empty-constructor-for-data-class-in-kotlin-android
     */
    constructor(): this(null, null, null)
}
  1. प्रत्येक इकाई में या तो एक डिफ़ॉल्ट कंस्ट्रक्टर होना चाहिए या उसके सभी मापदंडों के लिए डिफ़ॉल्ट होना चाहिए
  2. POJO को सेव करने के बजाय, Map<String, Any> . के रूप में सेव करें टाइप करें

चूंकि हमारे पास पूर्ण नियंत्रण है कि व्यावसायिक तर्क में पीओजेओ में क्या होगा, केवल लापता टुकड़ा पीओजेओ को मानचित्र और मानचित्र को पीओजेओ में परिवर्तित करना होगा

नमूनापूजो कार्यान्वयन

data class SamplePojo(
        val payload: String,
        val flag: Boolean
)  {
    constructor(map: Map<String, Any>) : this(map["payload"] as String, map["flag"] as Boolean)

    fun toMap() : Map<String, Any> {
        return mapOf("payload" to payload, "flag" to flag)
    }
}

यह एक समाधान है लेकिन यह हमें किसी भी गहराई-स्तर की संरचना के साथ काम करने की अनुमति देता है।

पी.एस. मैंने देखा है कि आप Serializer . का उपयोग करते हैं और फिर से परिभाषित equals, toString, hashCode . data class . का उपयोग करते समय आपको इसकी आवश्यकता नहीं है ।

अपडेट करें:

यदि आपको Map<String, Any> . से अधिक लचीली संरचना की आवश्यकता है , आप JsonNode . का उपयोग कर सकते हैं . कोड उदाहरण

इकाई:

import com.fasterxml.jackson.databind.JsonNode
import com.vladmihalcea.hibernate.type.json.JsonBinaryType
import com.vladmihalcea.hibernate.type.json.JsonStringType
import org.hibernate.annotations.Type
import org.hibernate.annotations.TypeDef
import org.hibernate.annotations.TypeDefs
import javax.persistence.*

@Entity
@Table(name = "tests")
@TypeDefs(
        TypeDef(name = "json", typeClass = JsonStringType::class),
        TypeDef(name = "jsonb", typeClass = JsonBinaryType::class)
)
data class SampleJsonNodeEntity (
        @Id @GeneratedValue
        val id: Long?,
        val name: String?,

        @Type(type = "jsonb")
        @Column(columnDefinition = "jsonb")
        var data: JsonNode?
) {

    /**
     * Dependently on use-case this can be done differently:
     * https://stackoverflow.com/questions/37873995/how-to-create-empty-constructor-for-data-class-in-kotlin-android
     */
    constructor(): this(null, null, null)
}

रिपोजिटरी में इकाई बदलें:

import com.example.demo.entity.SampleJsonNodeEntity
import org.springframework.data.jpa.repository.JpaRepository

interface SampleJsonNodeRepository: JpaRepository<SampleJsonNodeEntity, Long> {
}

दोनों तरीकों के लिए टेस्ट:

import com.example.demo.DbTestInitializer
import com.example.demo.entity.SampleJsonNodeEntity
import com.example.demo.entity.SampleMapEntity
import com.example.demo.pojo.SamplePojo
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertNotNull
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringRunner


@RunWith(SpringRunner::class)
@SpringBootTest
@ContextConfiguration(initializers = [DbTestInitializer::class])
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class SampleRepositoryTest {

    @Autowired
    lateinit var sampleMapRepository: SampleMapRepository

    @Autowired
    lateinit var sampleJsonNodeRepository: SampleJsonNodeRepository

    lateinit var dto: SamplePojo
    lateinit var mapEntity: SampleMapEntity
    lateinit var jsonNodeEntity: SampleJsonNodeEntity

    @Before
    fun setUp() {
        dto = SamplePojo("Test", true)
        mapEntity = SampleMapEntity(null,
                "POJO1",
                dto.toMap()
        )

        jsonNodeEntity = SampleJsonNodeEntity(null,
            "POJO2",
                jacksonObjectMapper().valueToTree(dto)
        )
    }

    @Test
    fun createMapPojo() {
        val id = sampleMapRepository.save(mapEntity).id!!
        assertNotNull(sampleMapRepository.getOne(id))
        assertEquals(sampleMapRepository.getOne(id).data?.let { SamplePojo(it) }, dto)
    }

    @Test
    fun createJsonNodePojo() {
        val id = sampleJsonNodeRepository.save(jsonNodeEntity).id!!
        assertNotNull(sampleJsonNodeRepository.getOne(id))
        assertEquals(jacksonObjectMapper().treeToValue(sampleJsonNodeRepository.getOne(id).data, SamplePojo::class.java), dto)
    }

}


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. AWS RDS डेटाबेस इंस्टेंस पर सुरक्षा समूह बदलें

  2. Psycopg2 / Python DB-API और PostgreSQL के साथ पैरामीटरयुक्त प्रश्न

  3. डेटा अंतराल के आधार पर समूहित करें

  4. PostgreSQL में डेटस्टाइल कैसे बदलें?

  5. अन्य पोस्टग्रेस्क्ल स्कीमा के लिए डेटाफ्रेम लिखने वाले पंडों