您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

SpringBoot + Kotlin + Postgres和JSONB:“org.hibernate.MappingException:JDBC类型没有方言映射”

SpringBoot + Kotlin + Postgres和JSONB:“org.hibernate.MappingException:JDBC类型没有方言映射”

我在请求请求中提出我的解决方

这个想法是将Entity更改为:

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)
}

由于我们可以完全控制业务逻辑中的POJO,因此唯一缺少的部分是将POJO转换为Map并将Map转换为POJO

SamplePojo实现

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)
    }
}

这是一种解决方法,但是它允许我们使用任何深度级别的结构。

PS我注意到您使用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)
    }

}
Postgres 2022/1/1 18:13:43 有712人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶