需求:
假如数据库某个表的一个字段是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里配置不能用".",要用"$",否则出错.
这样就可以了.

丰木
322 声望19 粉丝

遇见超乎想象的自己!


« 上一篇
sdf