在PGSQL中,有的类型是UUID和UUID[]这种类型,在mybatis和这些类型交互的时候需要手动设置类型处理器才可以,这里记录一下类型处理器的设置
/**
* UUID类型处理器
*/
public class UUIDTypeHandler extends BaseTypeHandler<UUID> {
/**
* 获取结果
*
* @param resultSet resultSet
* @param columnName 列名
* @return UUID结果
* @throws SQLException SQL异常
*/
@Override
public UUID getNullableResult(ResultSet resultSet, String columnName)
throws SQLException {
return getValue(resultSet.getString(columnName));
}
/**
* 获取结果
*
* @param rs 结果集
* @param columnIndex 列下标
* @return UUID结果
* @throws SQLException SQL异常
*/
@Override
public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getValue(rs.getString(columnIndex));
}
/**
* 获取结果
*
* @param cs cs
* @param columnIndex 列下标
* @return 返回UUID结果
* @throws SQLException SQL异常
*/
@Override
public UUID getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return getValue(cs.getString(columnIndex));
}
/**
* 设置参数
*
* @param ps ps
* @param i i
* @param parameter 参数
* @param jdbcType jdbc类型
* @throws SQLException SQL异常
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
if (null != parameter) {
ps.setObject(i, parameter);
}
}
/**
* 获取结果
*
* @param str 传参字符串
* @return 返回UUID结果
*/
private UUID getValue(String str) {
return notNull(str) ? UUID.fromString(str) : null;
}
/**
* 非空判断
*
* @param arg 参数
* @return 判断是否不为空
*/
private boolean notNull(String arg) {
return (null != arg && !arg.isEmpty());
}
}
/**
* UUID数组类型处理器
*/
public class UUIDArrTypeHandler extends BaseTypeHandler<List<UUID>> {
/**
* 设置参数
*
* @param ps PreparedStatement 对象
* @param i 参数索引
* @param parameter UUID 列表
* @param jdbcType JDBC 类型
* @throws SQLException SQL异常
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<UUID> parameter, JdbcType jdbcType) throws SQLException {
if (parameter != null) {
Array array = ps.getConnection().createArrayOf("uuid", parameter.toArray());
ps.setArray(i, array);
} else {
ps.setNull(i, Types.ARRAY);
}
}
/**
* 获取结果
*
* @param resultSet 结果集
* @param columnName 列名
* @return UUID 列表
* @throws SQLException SQL异常
*/
@Override
public List<UUID> getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
return getUUIDList(resultSet.getArray(columnName));
}
/**
* 获取结果
*
* @param rs 结果集
* @param columnIndex 列索引
* @return UUID 列表
* @throws SQLException SQL异常
*/
@Override
public List<UUID> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return getUUIDList(rs.getArray(columnIndex));
}
/**
* 获取结果
*
* @param cs CallableStatement 对象
* @param columnIndex 列索引
* @return UUID 列表
* @throws SQLException SQL异常
*/
@Override
public List<UUID> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return getUUIDList(cs.getArray(columnIndex));
}
/**
* 获取 UUID 列表
*
* @param array SQL 数组对象
* @return UUID 列表
* @throws SQLException SQL异常
*/
private List<UUID> getUUIDList(Array array) throws SQLException {
if (array == null) {
return null;
}
Object[] uuidArray = (Object[]) array.getArray();
List<UUID> result = new ArrayList<>();
for (Object obj : uuidArray) {
result.add((UUID) obj);
}
return result;
}
}
配置完之后需要在实体类的对应属性上添加注解以使其生效
@TableField(typeHandler = UUIDTypeHandler.class)
private UUID uuid;
@TableField(typeHandler = UUIDArrTypeHandler.class)
private List<UUID> memberBenefitUuids;
tips:我之前的项目里由于连接的pgSQL数据库有json/jsonb和uuid类型,对应的Java类型我设置的是String和UUID这种,但是在写类型处理器的时候发现如果不给(Java)UUID这种类型的类型处理器加入到Spring容器中,那么项目总是起不来,会报错【在xml中找不到UUID类型对应的类型处理器】,查找了一下,发现Springboot在集成mybatis的时候,启动时会注册所有的类型处理器,我们都知道mybatis自带了许多常用的类型处理器,所以大部分情况下都是不需要自定义的,但是自带的处理器中没有针对UUID去做处理的类型处理器,导致检测XML文件的时候发现了UUID这种类型但是找不到对应的类型处理器(如果你没有在XML中手动指定类型处理器,这是很常见的,因为有很多地方要指定,难免漏掉。但是你如果全部都手动指定的话也不会报错,但是很麻烦)就会报错java.lang.IllegalStateException: No typehandler found for property uuid
。所以这里需要针对UUID的类型处理器加上@Configuration注解,将它注册到容器中,这样在启动项目的时候mybatis就会检测到这个typeHandler,也就不会报错了。
部分源码如上图,这里就是在项目启动的时候尝试从容器中获取类型处理器
至于为什么json/jsonb的类型处理器不需要加注解,因为我Java中对应的类型是String,mybatis已经有了针对String类型处理的typeHandler,所以不会报错,但是实际使用还是要指定为自定义的typeHandler