当数据库中的字段的类型为 vacher ,是实体类中的类型为List<Integer> 、List<String>时,直接启动后控制台报错,提示属性没有对应的类型处理器,意思就是框架不知道怎么把java中的List和数据库的varchar怎么对应起来,这时候我们需要自定义类型处理器来告诉框架怎么进行类型的对应转换
一、自定义类型处理器
创建转换器类实现mybatis提供的TypeHandler接口,接口的泛型为Java中对应的数据类型,在这里使用List<String>类型,实现接口里面的方法,方法分为两类,其中setParameter()方法为插入数据库时,List数据转存varchar的规则,文中使用遍历List类型的入参,拼装为String类型,使用Statement对象插入数据库的方式来实现;剩余的三个方法均为将查询到的数据库varchar数据存入List集合的规则,文中使用获取String类型的结果,使用","分割为List后返回的规则实现。
1.在 util(工具包)中,定义 ListStringToVarcharTypeHandlerUtil(List<String>类型处理器)
package cn.com.fanjingxuan.util;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
/**
* @methodName ListStringToVarcharTypeHandlerUtil
* @effect: 类型转换器,用于数据库的varchar和Java中List<String>类型的相互转换
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class ListStringToVarcharTypeHandlerUtil implements TypeHandler<List<String>> {
@Override
public void setParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
// 遍历List类型的入参,拼装为String类型,使用Statement对象插入数据库
StringBuffer sb = new StringBuffer();
for (int j = 0; j < strings.size(); j++) {
if (j == strings.size() - 1) {
sb.append(strings.get(j));
} else {
sb.append(strings.get(j)).append(",");
}
}
preparedStatement.setString(i, sb.toString());
}
@Override
public List<String> getResult(ResultSet resultSet, String s) throws SQLException {
// 获取String类型的结果,使用","分割为List后返回
String resultString = resultSet.getString(s);
if (StringUtils.isNotEmpty(resultString)) {
return Arrays.asList(resultString.split(","));
}
return null;
}
@Override
public List<String> getResult(ResultSet resultSet, int i) throws SQLException {
// 获取String类型的结果,使用","分割为List后返回
String resultString = resultSet.getString(i);
if (StringUtils.isNotEmpty(resultString)) {
return Arrays.asList(resultString.split(","));
}
return null;
}
@Override
public List<String> getResult(CallableStatement callableStatement, int i) throws SQLException {
// 获取String类型的结果,使用","分割为List后返回
String resultString = callableStatement.getString(i);
if (StringUtils.isNotEmpty(resultString)) {
return Arrays.asList(resultString.split(","));
}
return null;
}
}
2.在 util(工具包)中,定义 ListIntegerToVarcharTypeHandlerUtil(List<Integer>类型处理器)
package cn.com.fanjingxuan.util;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @methodName ListIntegerToVarcharTypeHandlerUtil
* @effect: 类型转换器,用于数据库的varchar和Java中List<Integer>类型的相互转换
*/
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
public class ListIntegerToVarcharTypeHandlerUtil implements TypeHandler<List<Integer>> {
/**
* @methodName setParameter
* @effect: 将 List<Integer> 类型的数据转为 vacher 类型返回
*/
@Override
public void setParameter(PreparedStatement preparedStatement, int i, List<Integer> integers, JdbcType jdbcType) throws SQLException {
// 遍历List类型的入参,拼装为String类型,使用Statement对象插入数据库
//定义一个空的字符串缓冲区 sb ,含有16个字符的容量
StringBuffer sb = new StringBuffer();
for (int j = 0; j < integers.size(); j++) {
if (j == integers.size() - 1) {
sb.append(integers.get(j));
} else {
sb.append(integers.get(j)).append(",");
}
}
preparedStatement.setString(i, sb.toString());
}
/**
* @methodName getResult
* @effect: 将 vacher 类型的数据转为 List<Integer> 类型返回
*/
@Override
public List<Integer> getResult(ResultSet resultSet, String s) throws SQLException {
// 获取String类型的结果,使用","分割为List后返回
//resultSet.getString() 从 ResultSet 对象中获取 String 类型的数据
String resultString = resultSet.getString(s);
//判断 resultString 是否为空
if (StringUtils.isNotEmpty(resultString)) {
List<Integer> IntegerList = new ArrayList<Integer>();
String[] stringList = resultString.split(",");
//遍历元素,添加到IntegerList
for (String value : stringList) {
IntegerList.add(Integer.valueOf(value));
}
return IntegerList;
}
return null;
}
@Override
public List<Integer> getResult(ResultSet resultSet, int i) throws SQLException {
// 获取String类型的结果,使用","分割为List后返回
String resultString = resultSet.getString(i);
if (StringUtils.isNotEmpty(resultString)) {
List<Integer> IntegerList = new ArrayList<Integer>();
String[] stringList = resultString.split(",");
//遍历元素,添加到IntegerList
for (String value : stringList) {
IntegerList.add(Integer.valueOf(value));
}
return IntegerList;
}
return null;
}
@Override
public List<Integer> getResult(CallableStatement callableStatement, int i) throws SQLException {
// 获取String类型的结果,使用","分割为List后返回
String resultString = callableStatement.getString(i);
if (StringUtils.isNotEmpty(resultString)) {
List<Integer> IntegerList = new ArrayList<Integer>();
String[] stringList = resultString.split(",");
//遍历元素,添加到IntegerList
for (String value : stringList) {
IntegerList.add(Integer.valueOf(value));
}
return IntegerList;
}
return null;
}
}
二、 在类型转换器上添加注解
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes(List.class)
三、在Mapper文件中需要转换的字段使用我们刚刚自己实现的类型转换器
<!-- 可根据自己的需求,是否要使用 -->
<resultMap type="cn.com.fanjingxuan.model.User" id="userMap">
<result property="id" column="id"/>
<result property="employeeId" column="employee_id"/>
<result property="shopId" column="shop_id" typeHandler="cn.com.fanjingxuan.util.ListIntegerToVarcharTypeHandlerUtil"/>
<result property="position" column="position"/>
<result property="likeTime" column="like_time" typeHandler="cn.com.fanjingxuan.util.ListIntegerToVarcharTypeHandlerUtil"/>
<result property="likeDay" column="like_day" typeHandler="cn.com.fanjingxuan.util.ListIntegerToVarcharTypeHandlerUtil"/>
<result property="likeDuration" column="like_duration" />
<result property="maxTime" column="max_time"/>
<result property="food" column="food"/>
<result property="overtime" column="overtime"/>
<result property="created" column="created"/>
<result property="creator" column="creator"/>
<result property="edited" column="edited"/>
<result property="editor" column="editor"/>
<result property="deleted" column="deleted"/>
</resultMap>
如:修改的是 "shopId" , "likeTime" , "likeDay" 字段
至此,我们使用自定义类型处理器,优雅的完成了List集合的数据库存取操作