MyBatis借助BaseTypeHandler实现特殊的字段(数组或json)映射

问题背景

假设有一张表
CREATE TABLE `tb_event_info`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `event_no` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '事件编号',
  `event_title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '事件标题',
  `event_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '事件类型多个用\',\'隔开'
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1298 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '事件信息' ROW_FORMAT = Dynamic;

对应的entity

@TableName("event_info")
@Data
public class EventInfo extends Model<EventInfo> {

    private static final long serialVersionUID = 1L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 事件编号
     */
    private String eventNo;
    /**
     * 事件标题
     */
    private String eventTitle;
    /**
     * 事件类型
     */
    private String[] eventType;

}

event_type 存的是英文逗号隔开的字符串,如(11001,11002,11003), eventType 用String类型可以正常映射,如果我想用数组String[]来映射eventType,查出来的结果是[ 11001,11002,11003 ],这样的数组,如何操作呢?

实现代码

我们可以借助 org.apache.ibatis.type.BaseTypeHandler 这个类来实现,定义一个MyArrayTypeHandler类,继承它。


import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeException;

import java.sql.*;

/**
 * @Author: java890.com
 * @Date: 2021/10/19 14:05
 */
public class MyArrayTypeHandler extends BaseTypeHandler<String[]> {
    private static final String TYPE_NAME_VARCHAR = "varchar";
    private static final String TYPE_NAME_INTEGER = "integer";
    private static final String TYPE_NAME_BOOLEAN = "boolean";
    private static final String TYPE_NAME_NUMERIC = "numeric";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String[] parameter,
                                    JdbcType jdbcType) throws SQLException {

        String typeName = TYPE_NAME_VARCHAR;

        if (typeName == null) {
            throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
        }

        // 这3行是关键的代码,创建Array,然后ps.setArray(i, array)就可以了
        Connection conn = ps.getConnection();
        Array array = conn.createArrayOf(typeName, parameter);
        ps.setArray(i, array);
    }

    @Override
    public String[] getNullableResult(ResultSet rs, String columnName)
            throws SQLException {

        return getArray(rs.getString(columnName));
    }

    @Override
    public String[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {

        return getArray(rs.getString(columnIndex));
    }

    @Override
    public String[] getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {

        return getArray(cs.getString(columnIndex));
    }

    /**
     * 该方法就是把在 mapper xml 里配置了typeHandler=MyArrayTypeHandler的字段,
     * 走我们这个自定义方法来实现字符串转字符串数组
     * 同理,我们可以把它转成任何我们想转的格式,如Json
     * @param value
     * @return
     */
    private String[] getArray(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        return value.split(",");
    }

}

接下来就是EventInfoMapper.xml文件,只贴核心代码

<resultMap id="eventMap" type="com.xxxxx.EventInfo">
        <id column="id" property="id" />
        <result column="event_no" property="eventNo" />
        <result column="event_title" property="eventTitle" />
		<!-- 这一行就是核心的地方,要加上我们自定义的typeHandler类 -->
        <result column="event_type" property="eventType" typeHandler="com.xxxxx.handler.MyArrayTypeHandler" />
    </resultMap>

    <select id="pageSearch" resultMap="eventMap">
		select * from event_info
	</select>

查询结果

最后查出来就是我们想要的字符串数组结构

 

posted @ 2022-02-21 17:06  夏威夷8080  阅读(1455)  评论(0编辑  收藏  举报