【发布时间】:2020-05-14 22:57:06
【问题描述】:
所有文章都归结为以下选项:
- 注册具有
jsonb类型的自定义PostgreSQL95Dialect - 使用自定义映射实现 Hibernate 的
UserTypeinterface - 用自定义实现的
@TypeDef注释Entity - 在 application.properties 自定义方言中定义
如果上述所有操作都完成,代码应该可以工作。就我而言,我遇到了神秘的Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: property mapping has wrong number of columns: com.example.Book.header type: com.example.hibernate.BookHeaderType,我不知道如何进一步调试。
我的JsonbType抽象类:
abstract class JsonbType : UserType {
override fun hashCode(p0: Any?): Int {
return p0!!.hashCode()
}
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 equals(p0: Any?, p1: Any?): Boolean {
return p0 == p1
}
override fun assemble(p0: Serializable?, p1: Any?): Any {
return deepCopy(p0)
}
override fun disassemble(p0: Any?): Serializable {
return deepCopy(p0) as Serializable
}
override fun nullSafeSet(p0: PreparedStatement?, p1: Any?, 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
}
override fun sqlTypes(): kotlin.IntArray? {
return IntArray(Types.JAVA_OBJECT)
}
}
我的具体班级BookHeaderType 看起来:
class BookHeaderType : JsonbType() {
override fun returnedClass(): Class<BookBody> {
return BookBody::class.java
}
}
CustomPostgreSQLDialect.kt:
class CustomPostgreSQLDialect : PostgreSQL95Dialect {
constructor(): super() {
this.registerColumnType(Types.JAVA_OBJECT, "jsonb")
}
}
Book.kt实体:
@Entity
@Table(name = "book")
@TypeDefs(
TypeDef(name = "BookHeaderType", typeClass = BookHeaderType::class)
)
data class Book(
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(updatable = false, nullable = false)
val id: Long,
@Column(name = "header", nullable = false, columnDefinition = "jsonb")
@Type(type = "BookHeaderType")
var header: BookHeader
)
BookHeader.kt 实现可序列化
@JsonIgnoreProperties(ignoreUnknown = true)
data class BookHeader(
var createdAt: OffsetDateTime,
var createdBy: String
) : Serializable {
constructor() : this(OffsetDateTime.now(), "test")
}
我做错了什么? jsonb 自定义类型是否应该在 Kotlin 中以不同方式创建?
【问题讨论】:
-
也许还发布您的表定义。
-
你的 BookBody 是什么?
-
你解决了@DimytroChasovskyi 的问题吗?
-
@paranza 是的,我解决了。我基本上放弃了Hibernate,取了JdbcTemplate。不值得花时间。另外,我刚刚再次谷歌搜索了这个问题,发现hackish alternative。
-
@paranza 你还在为这个问题而苦恼吗?您能否添加一个指向将显示问题的引导项目的链接,以便我们可以更新此问题并创建答案,以便其他人也可以从中受益?
标签: postgresql hibernate kotlin jsonb