JPA @Converter注解不生效,MyBatis启动提示metadata无对应类型处理器
问题根本原因
你使用的@Convert是JPA规范提供的转换器注解,仅在使用JPA持久化能力时生效,当前实际持久化层用的是MyBatis,MyBatis无法识别该注解,也找不到对应HomeMasterDataMetadata类型和数据库longtext类型的转换处理器,因此报类型处理器缺失的错误。
解决方案步骤
1. 替换JPA转换器为MyBatis自定义TypeHandler
删除原来实现AttributeConverter的转换器类,新增MyBatis的类型处理器:
import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import org.springframework.stereotype.Component; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @Component @MappedTypes(HomeMasterDataMetadata.class) @MappedJdbcTypes(JdbcType.LONGVARCHAR) public class MetadataTypeHandler extends BaseTypeHandler<HomeMasterDataMetadata> { private final ObjectMapper objectMapper; // Spring会自动注入ObjectMapper public MetadataTypeHandler(ObjectMapper objectMapper) { this.objectMapper = objectMapper; } @SneakyThrows @Override public void setNonNullParameter(PreparedStatement ps, int i, HomeMasterDataMetadata parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, objectMapper.writeValueAsString(parameter)); } @SneakyThrows @Override public HomeMasterDataMetadata getNullableResult(ResultSet rs, String columnName) throws SQLException { String json = rs.getString(columnName); return json == null ? null : objectMapper.readValue(json, HomeMasterDataMetadata.class); } @SneakyThrows @Override public HomeMasterDataMetadata getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String json = rs.getString(columnIndex); return json == null ? null : objectMapper.readValue(json, HomeMasterDataMetadata.class); } @SneakyThrows @Override public HomeMasterDataMetadata getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String json = cs.getString(columnIndex); return json == null ? null : objectMapper.readValue(json, HomeMasterDataMetadata.class); } }
2. 配置MyBatis扫描自定义类型处理器
在application.yml(或application.properties)中添加配置,指定类型处理器所在的包路径:
mybatis: type-handlers-package: com.example.mybatiscomplexpersistance.handler # 替换为你TypeHandler实际所在的包
3. 修正Mapper中的错误
你当前Insert语句的表名写错了,实际创建的表是HomeMasterData,但你写的是CLMMasterData,修正后如下:
@Mapper public interface userMapper { @Insert("Insert into HomeMasterData (CustomerId,CreditLimit,canBuy,EMI,metadata) values(#{customerId}, #{creditLimit},#{canBuy},#{Emi},#{metadata})") int insertCLMMasterData(HomeMasterData homeMasterData); @Select("select * from HomeMasterData where CustomerId = #{Id}") HomeMasterData getCustomerById(@Param("Id") int customerId); }
可选:局部指定类型处理器
如果不想全局配置,也可以在参数占位符处手动指定类型处理器:
@Insert("Insert into HomeMasterData (CustomerId,CreditLimit,canBuy,EMI,metadata) values(#{customerId}, #{creditLimit},#{canBuy},#{Emi},#{metadata,typeHandler=com.example.mybatiscomplexpersistance.handler.MetadataTypeHandler})") int insertCLMMasterData(HomeMasterData homeMasterData);
查询时需要指定结果映射的话,添加@Results注解即可:
@Select("select * from HomeMasterData where CustomerId = #{Id}") @Results(id = "HomeMasterDataMap", value = { @Result(column = "metadata", property = "metadata", typeHandler = MetadataTypeHandler.class) }) HomeMasterData getCustomerById(@Param("Id") int customerId);
其他注意事项
实体类上的JPA相关注解(@Entity、@Table、@Convert等)如果没有用到JPA持久化能力,可以直接删除,避免不必要的混淆。
内容的提问来源于stack exchange,提问作者Rabbani
相关产品推荐
相关产品推荐

