需求:
假如数据库某个表的一个字段是json
数据类型, 字段名是students
,类型是, 存的是json格式的学生数组,现要用一个List<Student>来接收,如何实现自动转换.
1. 实现TypeHandler
why?
如果json字段存的是数组, 直接使用 "com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler" 会给你转成List<JSONObject>类型; 所以需要自己转.
1.1 定义handler: ListTypeHandler
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.commons.collections4.CollectionUtils;
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 java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* 用来将数据库中的json类型的字段, 转为List时使用(否则默认会转成List<JSONObject>格式)
*
* @param <T>
* @author niewj
* @date 2024-12-18 20:01
*/
@MappedJdbcTypes(JdbcType.VARBINARY)
@MappedTypes({List.class})
public abstract class ListTypeHandler<T> extends BaseTypeHandler<List<T>> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
String content = CollectionUtils.isEmpty(parameter) ? null : JSON.toJSONString(parameter);
ps.setString(i, content);
}
@Override
public List<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
return this.getListByJsonArrayString(rs.getString(columnName));
}
@Override
public List<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return this.getListByJsonArrayString(rs.getString(columnIndex));
}
@Override
public List<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return this.getListByJsonArrayString(cs.getString(columnIndex));
}
private List<T> getListByJsonArrayString(String content) {
return StringUtils.isBlank(content) ? new ArrayList<>() : JSON.parseObject(content, this.specificType());
}
/**
* 具体类型,由子类提供
*
* @return 具体类型
*/
protected abstract TypeReference<List<T>> specificType();
}
1.2 定义具体实现
我这耍懒了, 都写到一个类里
import com.alibaba.fastjson.TypeReference;
import com.niewj.model.Student;
import java.util.List;
/**
* 将需要实现的具体List<T>的T类型实现类定义在此处
*
* @author niewj
* @date 2024-12-18 20:10
*/
public class ConcreteListTypeHandler {
/**
* Student 类型的List转换
*/
public static class StudentHandler extends ListTypeHandler<Student> {
@Override
protected TypeReference<List<Student>> specificType() {
return new TypeReference<List<Student>>() {
};
}
}
}
2. 配置: 实体类和mapper.xml
2.1 实体类
@TableName(value ="rec_xxx", autoResultMap = true) // `autoResultMap = true`不能少
@Data
public class RecXXXDO implements Serializable {
// ...
@TableField(typeHandler = ConcreteListTypeHandler.StudentHandler.class)
private List<Student> students;
2.2 mapper.xml
<result property="students" column="students" typeHandler="com.niewj.handler.ConcreteListTypeHandler$StudentHandler"/>
记得这里用的是静态内部类,内部类在xml里配置不能用".",要用"$",否则出错.
这样就可以了.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。