Hibernate
可以自定义一些类型转换器,即从java
对象转换成数据库中的值,或者把数据库中的值转成java
对象。JsonType
即在保存时把java
对象转换成json
字符串存在数据库,在读取数据库时再把json
字符串转成对应的java
对象。
自定义类型需要实现UserType
接口,并实现对应方法
这只是一个简单的实现,仅在H2
数据库中和Hibernate 6
中使用没问题,其hypersistence-utils
适配了各种数据库,并支持Hibernate
的各种版本
class JsonType: UserType<Any>, DynamicParameterizedType {
private lateinit var className: String
override fun setParameterValues(parameters: Properties) {
className = parameters.getProperty("org.hibernate.type.ParameterType.returnedClass")
}
override fun equals(x: Any?, y: Any?): Boolean {
return x == y
}
override fun hashCode(x: Any?): Int {
return x?.hashCode() ?: 0
}
override fun returnedClass(): Class<Any> {
return javaType.javaTypeClass
}
private val javaType = ObjectJavaType.INSTANCE
override fun getSqlType(): Int {
return Types.VARCHAR
}
override fun nullSafeGet(
rs: ResultSet,
position: Int,
session: SharedSessionContractImplementor?,
owner: Any?
): Any {
val value = rs.getObject(position)
return SpringUtils.getBean<ObjectMapper>().readValue(value?.toString() ?: "{}", Class.forName(className))
}
override fun nullSafeSet(
st: PreparedStatement,
value: Any?,
index: Int,
session: SharedSessionContractImplementor?
) {
if (value == null) {
st.setObject(index, "{}")
} else {
val bean = SpringUtils.getBean<ObjectMapper>()
bean.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY)
st.setObject(index, SpringUtils.getBean<ObjectMapper>().writeValueAsString(value))
}
}
override fun deepCopy(value: Any?): Any? {
return value
}
override fun isMutable(): Boolean {
return true
}
override fun disassemble(value: Any?): Serializable {
TODO("Not yet implemented")
}
override fun assemble(cached: Serializable?, owner: Any?): Any {
TODO("Not yet implemented")
}
override fun replace(detached: Any?, managed: Any?, owner: Any?): Any {
TODO("Not yet implemented")
}
}
其中,SpringUtils
@Component
@Lazy(false)
class SpringUtils: ApplicationContextAware {
companion object {
lateinit var applicationContext: ApplicationContext
inline fun <reified T: Any> getBean(name: String): T {
return applicationContext.getBean(name) as T
}
inline fun <reified T: Any> getBean() = applicationContext.getBean(T::class.java)
}
override fun setApplicationContext(applicationContext: ApplicationContext) {
SpringUtils.applicationContext = applicationContext
}
}
使用,在对应的实体类属性上标明注解
@Type(value = JsonType::class)
1 条评论
真棒!