java - 如何在 MyBatis 中使用带有 @Many 注释的 UUID 类型处理程序?
问题描述
我正在使用 2.1.0 版本的 mybatis-spring-boot-starter。而且我需要处理 UUID 类型以获取嵌套集合。
@Select("SELECT id, name FROM t_service s")
@Results(value = {
@Result(column = "id", property = "id", jdbcType = JdbcType.OTHER, typeHandler = UuidTypeHandler.class),
@Result(column = "name", property = "name"),
@Result(property = "rates", column = "id", javaType = List.class, many = @Many(select = "getAllRates"))
})
List<Service> findAll();
@Select("SELECT date_from, date_to, currency FROM t_rate where t_rate.service_id = #{serviceId, javaType=java.util.UUID, jdbcType=OTHER, typeHandler=my.package.UuidTypeHandler}")
@Results(value = {
@Result(property = "dateFrom", column = "date_from"),
@Result(property = "dateTo", column = "date_to"),
@Result(property = "currency", column = "currency")
})
List<Rate> getAllRates(@Param("serviceId") UUID serviceId);
UuidTypeHandler:
@MappedJdbcTypes(JdbcType.OTHER)
@MappedTypes(UUID.class)
public class UuidTypeHandler extends BaseTypeHandler<UUID> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
ps.setObject(i, parameter, jdbcType.TYPE_CODE);
}
@Override
public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getObject(columnName, UUID.class);
}
@Override
public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getObject(columnIndex, UUID.class);
}
@Override
public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getObject(columnIndex, UUID.class);
}
}
但我得到以下异常:
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'serviceId' in 'class java.util.UUID'
在其他情况下(直接调用方法时)UuidTypeHandler 工作正常,我没有任何问题
PostgreSQL 的解决方法:
@Select("SELECT date_from, date_to, currency FROM t_rate where t_rate.service_id = #{serviceId}::uuid")
@Results(value = {
@Result(property = "dateFrom", column = "date_from"),
@Result(property = "dateTo", column = "date_to"),
@Result(property = "currency", column = "currency")
})
List<Rate> getAllRates(@Param("serviceId") String serviceId);
解决方案
要使其工作,您需要在配置中全局注册类型处理程序(这是一种限制)。
在您的情况下,添加mybatis.type-handlers-package=my.package
到 application.properties 就足够了。
在全局注册类型处理程序后,在大多数情况下,您可以在映射器中省略typeHandler
。
@Select("SELECT id, name FROM t_service s")
@Results(value = {
@Result(column = "id", property = "id"),
@Result(column = "name", property = "name"),
@Result(property = "rates", column = "id",
javaType = List.class, many = @Many(select = "getAllRates"))
})
List<Service> findAll();
@Select("SELECT date_from, date_to, currency FROM t_rate where t_rate.service_id = #{serviceId}")
@Results(value = {
@Result(property = "dateFrom", column = "date_from"),
@Result(property = "dateTo", column = "date_to"),
@Result(property = "currency", column = "currency")
})
List<Rate> getAllRates(@Param("serviceId") UUID serviceId);
类型处理程序也可以稍微简单一些。
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
// no @MappedJdbcTypes
@MappedTypes(UUID.class)
public class UuidTypeHandler extends BaseTypeHandler<UUID> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
ps.setObject(i, parameter); // no 3rd arg
}
@Override
public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
return rs.getObject(columnName, UUID.class);
}
@Override
public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return rs.getObject(columnIndex, UUID.class);
}
@Override
public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return cs.getObject(columnIndex, UUID.class);
}
}
推荐阅读
- android - Kotlin:没有找到类“java.time.LocalDateTime”
- sparql - SPARQL 中的拆分、排序和连接
- reactjs - 使用 jest 和 enzymne 测试自定义反应钩子时出错
- javascript - 使用 Material Steppers 的脚本中的步骤识别错误
- html - 视频预加载:在 Chrome 中必须有一个有效的 `as` 值
- php - 在一个控制器函数中使用 laravel delete() 三次
- terraform - Terraform:使用文件插值从模块中读取本地文件
- regex - One-liner to extract domain from email address
- swift - 编译时自定义 NSTableCellView 给了我“在展开可选值时意外发现 nil”
- c++ - 我该如何优化这个侵蚀过滤器代码?