解决 Mybatis Plus字段类型擦除问题
自定义字段类型处理器:
package com.xxx.common.handler
import cn.hutool.core.util.StrUtil
import com.fasterxml.jackson.core.JsonParseException
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.type.TypeFactory
import com.rollong.common.json.JSONUtil.toJSONString
import org.apache.ibatis.type.BaseTypeHandler
import org.apache.ibatis.type.JdbcType
import org.springframework.core.ResolvableType
import org.springframework.util.Assert
import java.io.IOException
import java.lang.reflect.Type
import java.sql.CallableStatement
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException
/**
* 自定义字段类型处理器:为了解决字段类型处理器泛型被擦除的问题
* @author flicker
*/
abstract class BaseAttributeTypeHandler<T> : BaseTypeHandler<Any?>() {
private val javaType: JavaType
/**
* 构造方法
*/
init {
val resolvableType = ResolvableType.forClass(javaClass)
val type = resolvableType.`as`(BaseAttributeTypeHandler::class.java).getGeneric().type
javaType = constructType(type)
}
@Throws(SQLException::class)
override fun setNonNullParameter(ps: PreparedStatement, i: Int, parameter: Any?, jdbcType: JdbcType) {
ps.setString(i, toJSONString(parameter!!))
}
@Throws(SQLException::class)
override fun getNullableResult(rs: ResultSet, columnName: String): Any? {
val value = rs.getString(columnName)
return convertToEntityAttribute(value)
}
@Throws(SQLException::class)
override fun getNullableResult(rs: ResultSet, columnIndex: Int): Any? {
return convertToEntityAttribute(rs.getString(columnIndex))
}
@Throws(SQLException::class)
override fun getNullableResult(cs: CallableStatement, columnIndex: Int): Any? {
val value = cs.getString(columnIndex)
return convertToEntityAttribute(value)
}
private fun convertToEntityAttribute(dbData: String): Any? {
return if (StrUtil.isEmpty(dbData)) {
if (MutableList::class.java.isAssignableFrom(javaType.rawClass)) {
emptyList<Any>()
} else if (MutableSet::class.java.isAssignableFrom(javaType.rawClass)) {
emptySet<Any>()
} else if (MutableMap::class.java.isAssignableFrom(javaType.rawClass)) {
emptyMap<Any, Any>()
} else {
null
}
} else toObject<Any>(
dbData,
javaType
)
}
companion object {
/**
* ObjectMapper
*/
private val OBJECT_MAPPER = ObjectMapper()
private fun constructType(type: Type): JavaType {
Assert.notNull(type, "[Assertion failed] - type is required; it must not be null")
return TypeFactory.defaultInstance().constructType(type)
}
private fun <T> toObject(json: String, javaType: JavaType): T {
Assert.hasText(json, "[Assertion failed] - this json must have text; it must not be null, empty, or blank")
Assert.notNull(javaType, "[Assertion failed] - javaType is required; it must not be null")
return try {
OBJECT_MAPPER.readValue(json, javaType)
} catch (e: JsonParseException) {
throw RuntimeException(e.message, e)
} catch (e: JsonMappingException) {
throw RuntimeException(e.message, e)
} catch (e: IOException) {
throw RuntimeException(e.message, e)
}
}
}
}
使用:
@TableField(typeHandler = VCContentHandler::class)
var content: List<ViewComponentContent>? = null
class VCContentHandler : BaseAttributeTypeHandler<List<ViewComponentContent>>(JsonObjectType.jsonb)
参考资料:
MyBatis-Plus - 字段类型处理器之泛型擦除解决方案_放羊的牧码的博客-CSDN博客_mybatis plus 泛型
希望实现一个通用的嵌套泛型的TypeHandler · Issue #I4SCBF · baomidou/mybatis-plus - Gitee.com