程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了SpringBoot + Kotlin + Postgres和JSONB:“org.hibernate.MappingException:JDBC类型没有方言映射”大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决SpringBoot + Kotlin + POSTGRes和JSONB:“Org.hibernate.MappingException:JDBC类型没有方言映射”?

开发过程中遇到SpringBoot + Kotlin + POSTGRes和JSONB:“Org.hibernate.MappingException:JDBC类型没有方言映射”的问题如何解决?下面主要结合日常开发的经验,给出你关于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)
}
  1. 每个实体都应具有默认构造函数或所有参数都具有默认值
  2. 而不是保存POJO,另存为@H_850_7@map<String, Any>类型

由于我们可以完全控制业务逻辑中的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

如果您需要比以上更灵活的结构@H_850_7@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)
    }

}

解决方法

我一直在咨询许多方法/帖子/堆栈溢出问题,以便在运行Kotlin / SpringBoot应用程序时处理以下错误(完整堆栈跟踪):

2020-04-22 18:33:56.823 ERROR 46345 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.beanCreationException: Error creaTing bean with name 'entitymanagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: No Dialect mapping for JDBC type: 2118910070
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1803)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at app.ApplicationKt.main(Application.kt:13)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegaTingMethodAccessorImpl.invoke(DelegaTingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: No Dialect mapping for JDBC type: 2118910070
    at org.springframework.orm.jpa.AbstractEntitymanagerFactoryBean.buildNativeEntitymanagerFactory(AbstractEntitymanagerFactoryBean.java:403)
    at org.springframework.orm.jpa.AbstractEntitymanagerFactoryBean.afterPropertiesSet(AbstractEntitymanagerFactoryBean.java:378)
    at org.springframework.orm.jpa.LocalContainerEntitymanagerFactoryBean.afterPropertiesSet(LocalContainerEntitymanagerFactoryBean.java:341)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1862)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1799)
    ... 21 common frames omitted
Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: 2118910070
    at org.hibernate.dialect.Typenames.get(Typenames.java:71)
    at org.hibernate.dialect.Typenames.get(Typenames.java:103)
    at org.hibernate.dialect.Dialect.getTypename(Dialect.java:369)
    at org.hibernate.mapping.column.getSqlType(column.java:238)
    at org.hibernate.tool.scheR_925_11845@a.internal.AbstractscheR_925_11845@aValidator.validatecolumnType(AbstractscheR_925_11845@aValidator.java:156)
    at org.hibernate.tool.scheR_925_11845@a.internal.AbstractscheR_925_11845@aValidator.validateTable(AbstractscheR_925_11845@aValidator.java:143)
    at org.hibernate.tool.scheR_925_11845@a.internal.GroupedscheR_925_11845@aValidatorImpl.validateTables(GroupedscheR_925_11845@aValidatorImpl.java:42)
    at org.hibernate.tool.scheR_925_11845@a.internal.AbstractscheR_925_11845@aValidator.performValidation(AbstractscheR_925_11845@aValidator.java:89)
    at org.hibernate.tool.scheR_925_11845@a.internal.AbstractscheR_925_11845@aValidator.doValidation(AbstractscheR_925_11845@aValidator.java:68)
    at org.hibernate.tool.scheR_925_11845@a.spi.scheR_925_11845@aManagementToolCoordinator.performDatabaseAction(scheR_925_11845@aManagementToolCoordinator.java:192)
    at org.hibernate.tool.scheR_925_11845@a.spi.scheR_925_11845@aManagementToolCoordinator.process(scheR_925_11845@aManagementToolCoordinator.java:73)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:320)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:462)
    at org.hibernate.jpa.boot.internal.EntitymanagerFactoryBuilderImpl.build(EntitymanagerFactoryBuilderImpl.java:1249)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntitymanagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
    at org.springframework.orm.jpa.LocalContainerEntitymanagerFactoryBean.createNativeEntitymanagerFactory(LocalContainerEntitymanagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntitymanagerFactoryBean.buildNativeEntitymanagerFactory(AbstractEntitymanagerFactoryBean.java:391)
    ... 25 common frames omitted

问题在于使用Hibernate映射POSTGReSQL的JSONB数据类型。

我广泛尝试和调试的2种方法如下:

  1. 实现自定义hibernate映射并为JSONB创建自定义UserType。参:这里,这里,这里
  2. 使用hibernate类型。参资料在这里,这里和这里

我在这两个方面都进行了很多尝试,但是没有运气,而且我很想知道我要去哪里错了,我一直想念什么。

方法1

我的实体:

@Entity
@TypeDef(name = "JsonUserType",typeClass = JsonUserType::class)
@Table(name = "entity")
data class MyEntity(
  @column(nullable = falsE)
  val id: UUID,@column(nullable = falsE)
  @Enumerated(value = EnumType.StriNG)
  @column(nullable = falsE)
  val type: Type,@Type(type = "JsonUserType")
  @column(columnDefinition = "jsonb")
  @Basic(fetch = FetchType.LAZY)
  var event_data: Event
) : SomeEntity<UUID>(),SomeOtherstuff {
  override fun getName(): String {
    return id
  }
}


enum class Type(val value: String) {
  TYPE1("Type1"),TYPE2("Type2")
}

我的PoJO:

data class Event(
  val someContent: String,val someBoolean: Boolean
) : serializable { //equals,hashcode etc are omitted }

我的自定义hibernate方言:

class CustomPOSTGReSQLDialect : POSTGReSQL95Dialect {
  constructor() : super() {
    this.registercolumnType(Types.JAVA_OBjeCT,"jsonb")
  }
}

我的自定义类型(抽象类)

abstract class JsonDataUserType : UserType {

  override fun sqlTypes(): IntArray? {
    return intArrayOf(Types.JAVA_OBjeCT)
  }

  override fun equals(value1: Any?,value2: Any?): Boolean {
    return value1 == value2
  }

  override fun hashCode(value1: Any?): Int {
    return value1!!.hashCode()
  }

  override fun assemble(value1: serializable?,value2: Any?): Any {
    return deepCopy(value1)
  }

  override fun disassemble(value1: Any?): serializable {
    return deepCopy(value1) as serializable
  }

  override fun deepCopy(p0: Any?): Any {
    return try {
      val bos = ByteArrayOutputStream()
      val oos = ObjectOutputStream(bos)
      oos.writeObject(p0)
      oos.flush()
      oos.close()
      bos.close()
      val bais = ByteArrayInputStream(bos.toByteArray())
      ObjecTinputStream(bais).readObject()
    } catch (ex: ClassnotFoundException) {
      throw HibernateException(eX)
    } catch (ex: IOException) {
      throw HibernateException(eX)
    }
  }

  override fun replace(p0: Any?,p1: Any?,p2: Any?): Any {
    return deepCopy(p0)
  }

  override fun nullSafeSet(p0: PreparedStatement?,p2: Int,p3: SharedSessionContractimplementor?) {
    if (p1 == null) {
      p0?.setNull(p2,Types.OTHER)
      return
    }
    try {
      val mapper = ObjectMapper()
      val w = StringWriter()
      mapper.writeValue(w,p1)
      w.flush()
      p0?.setObject(p2,w.toString(),Types.OTHER)
    } catch (ex: java.lang.Exception) {
      throw RuntimeException("Failed to convert Jsonb to String: " + ex.message,eX)
    }
  }
  override fun nullSafeGet(p0: ResultSet?,p1: Array<out String>?,p2: SharedSessionContractimplementor?,p3: Any?): Any {
    val cellContent = p0?.getString(p1?.get(0))
    return try {
      val mapper = ObjectMapper()
      mapper.readValue(cellContent?.toByteArray(charset("UTF-8")),returnedClass())
    } catch (ex: Exception) {
      throw RuntimeException("Failed to convert String to Jsonb: " + ex.message,eX)
    }
  }

  override fun isMutable(): Boolean {
    return true
  }

}

我的具体课程:

class JsonType : JsonDataUserType() {
    override fun returnedClass(): Class<Event> {
      return Event::class.java
    }
}

我的application.yml jpahibernate属性

jpa.properties.database.database-platform: org.hibernate.dialect.POSTGReSQL95Dialect
jpa.properties.hibernate.dialect: org.myapp.util.CustomPOSTGReSQLDialect

方法2

Hibernate属性与PoJo类完全相同,不包含自定义映射器。

实体

@Entity
@TypeDef(
  name = "jsonb",typeClass = JsonBinaryType::class
)
@Table(name = "entity")
data class MyEntity(
  @column(nullable = falsE)
  val id: UUID,@Type(type = "jsonb")
  @column(columnDefinition = "jsonb")
  @Basic(fetch = FetchType.LAZY)
  var event_data: Event
) : SomeEntity<UUID>(),TYPE2("Type2")
}

自定义方言(使用hibernate类型):

class CustomPOSTGReSQLDialect : POSTGReSQL95Dialect {
  constructor() : super() {
    this.registerHibernateType(Types.OTHER,JsonNodeBinaryType::class.java.Name)
    this.registerHibernateType(Types.OTHER,JsonStringType::class.java.Name)
    this.registerHibernateType(Types.OTHER,JsonBinaryType::class.java.Name)
    this.registerHibernateType(Types.OTHER,JsonNodeStringType::class.java.Name)
  }
}

请注意,我也尝试仅使用:

this.registerHibernateType(Types.OTHER,"jsonb")

以及所有这些都存在于我的实体或其扩展的基础实体中(对此没有更改):

@TypeDefs({
    @TypeDef(name = "String-array",typeClass = StringArrayType.class),@TypeDef(name = "int-array",typeClass = IntArrayType.class),@TypeDef(name = "json",typeClass = JsonStringType.class),@TypeDef(name = "jsonb",typeClass = JsonBinaryType.class),@TypeDef(name = "jsonb-node",typeClass = JsonNodeBinaryType.class),@TypeDef(name = "json-node",typeClass = JsonNodeStringType.class),})

在这两种方法中我都明显做错了吗?我无法使其正常工作,并且不确定是否以任何方式相关, JDBC类型的No Dialect映射
之后的数值始终是不同的。我添加此代码是因为我看到某些ID与某些错误类别相关。

你能帮我吗?

谢谢

编辑: 我想提供有关jpa,POSTGRes和hibernate版本的更多信息。我目前正在与以下人员合作:

  1. POSTGRes:10-高山
  2. PostgreSQL JDBC驱动程序JDBC 4.2»42.2.8
  3. org.springframework.boot:spring-boot-starter-data-jpa:2.2.1.RELEASE
  4. org.hibernate:hibernate-core:5.4.8。最终

其中是否存在任何特定的版本控制问题?

编辑2 我一直试图成功使用hibernate类型(如上所述的方法2)。根据POSTGRes版本(10),我进行了以下更改:

class CustomPOSTGReSQLDialect : POSTGReSQL10Dialect {
  constructor() : super() {
    this.registerHibernateType(Types.OTHER,StringArrayType::class.java.Name)
    this.registerHibernateType(Types.OTHER,IntArrayType::class.java.Name)
    this.registerHibernateType(Types.OTHER,JsonNodeStringType::class.java.Name)
  }
}

然后在我的实体中

@TypeDefs({
        @TypeDef(name = "String-array",typeClass = JsonBinaryType.class)
})

 @Type(type = "jsonb")
 @column(columnDefinition = "jsonb")
 @Basic(fetch = FetchType.LAZY)
 var event_data: Event

然后,我已经在 Typenames 中调试了 get 方法,其中错误来自: __

public String get(final int typeCodE) throws MappingException {
        final Integer Integer = Integer.valueOf( typeCode );
        final String result = defaults.get( Integer );
        if ( result == null ) {
            throw new MappingException( "No Dialect mapping for JDBC type: " + typeCode );
        }
        return result;
    }

这就是我得到的:

defaults = {HashMap@12093}  size = 27
     {Integer@12124} -1 -> "text"
     {Integer@12126} 1 -> "char(1)"
     {Integer@12128} -2 -> "bytea"
     {Integer@12130} 2 -> "numeric($p,$s)"
     {Integer@12132} -3 -> "bytea"
     {Integer@12133} -4 -> "bytea"
     {Integer@12134} 4 -> "int4"
     {Integer@12136} -5 -> "int8"
     {Integer@12138} -6 -> "int2"
     {Integer@12140} 5 -> "int2"
     {Integer@12141} -7 -> "bool"
     {Integer@12143} 6 -> "float4"
     {Integer@12145} 7 -> "real"
     {Integer@12147} 8 -> "float8"
     {Integer@12149} -9 -> "nvarchar($l)"
     {Integer@12151} 12 -> "varchar($l)"
     {Integer@12153} -15 -> "nchar($l)"
     {Integer@12155} -16 -> "nvarchar($l)"
     {Integer@12156} 16 -> "Boolean"
     {Integer@12158} 2000 -> "json"
     {Integer@12160} 2004 -> "oid"
     {Integer@12162} 2005 -> "text"
     {Integer@12163} 1111 -> "uuid"
     {Integer@12165} 91 -> "date"
     {Integer@12167} 2011 -> "nclob"
     {Integer@12169} 92 -> "time"
     {Integer@12171} 93 -> "timestamp"

找不到 jsonb ,当我调试自定义方言时,得到以下信息:

{Integer@10846} 1111 -> "com.vladmihalcea.hibernate.type.json.JsonStringType"
 key = {Integer@10846} 1111
 value = "com.vladmihalcea.hibernate.type.json.JsonStringType"

这是为什么?为什么我没有得到jsonb类型?

@H_675_224@@H_675_224@
@H_675_224@

大佬总结

以上是大佬教程为你收集整理的SpringBoot + Kotlin + Postgres和JSONB:“org.hibernate.MappingException:JDBC类型没有方言映射”全部内容,希望文章能够帮你解决SpringBoot + Kotlin + Postgres和JSONB:“org.hibernate.MappingException:JDBC类型没有方言映射”所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。