MyBatis(mybatis_plus)中TypeHandler的使用教程

MyBatis(mybatis_plus)中TypeHandler的使用教程

一.TypeHandler作用及其使用场景

在我们平常开发操作数据库时,查询、插入数据等操作行为,有时会报数据类型不匹配异常,就可以得知数据的类型是不唯一的必然是多种不同的数据类型。并且我们必须要明确的一点就是java作为一门编程语言有自己的数据类型,数据库也是有自己的数据类型的。

jdbc数据类型:org.apache.ibatis.type.JdbcType 此枚举就是所有的数据库支持类型

java数据类型:int、long、string、...

一定要分清,例如java重的date数据插入到数据库中,应该是已经转换成了数据库的某种类型,必然跟java已经没有关系了。中间有一些我们看不见的操作做了数据处理。

假设此时的java类型与数据库数据类型是一样的,哪么其他语言中的日期数据插入数据库时又该怎么解释,例如C#操作数据库存入时间类型,C#与java肯定没有关系吧。所以每种语言与数据库之间有种数据类型关系对应。

思考:

因为java与数据库各自有数据类型,所以在将java数据存入数据库前中间是否有其他操作,是我们看不见的,不然java数据怎么知道自己与哪个jdbc数据类型匹配?

答:mybatis框架为每种数据类型做了默认的关系对应,BaseTypeHandler的所有实现类,就是来做这些处理的。

例如:java中的date插入数据库时是jdbc哪种类型,怎么就是这种类型? 中间具体有什么操作?

答:DateTypeHandler就是来解决date数据类型的处理。

二.TypeHandler使用

我们想要自定义去处理Java和JDBC的数据类型转换时,需要实现TypeHandler接口,该接口源码如下:

//此接口作用是用于指定jdbc与java的数据类型间对应关系处理。
public interface TypeHandler<T> {
  // 保存操作,数据入库之前时数据处理
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
  //下面三个则是,从数据库加载数据后,vo对象封装前的数据处理
  T getResult(ResultSet rs, String columnName) throws SQLException;
  T getResult(ResultSet rs, int columnIndex) throws SQLException;
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

JsonIntegerTypeHandler 实现Integer和字符串互转

public class JsonIntegerTypeHandler extends BaseTypeHandler<Integer> {
    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, toJson(parameter));
    }

    @Override
    public Integer getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return this.toObject(rs.getString(columnName));
    }

    @Override
    public Integer getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return this.toObject(rs.getString(columnIndex));
    }

    @Override
    public Integer getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return this.toObject(cs.getString(columnIndex));
    }

    private String toJson(Integer params) {
        try {
            String copyObject = IotDbUtils.copyObject(params);
            return copyObject;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    private Integer toObject(String content) {
        if (content != null && !content.isEmpty()) {
            try {
                System.out.println("1111111111111"+content);
                return (Integer) mapper.readValue(content, Integer.class);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            return null;
        }
    }
}

Mapper.xml

查询

查询的时候 你转的那个字段就配置哪个字段

    <resultMap id="DmpDeviceReportResult" type="com.chinaunicom.iotdb.domain.DmpDeviceReportInformation" >
        <result column="Time" property="timestamp" />

        <result column="type" jdbcType="INTEGER"
                property="type" typeHandler="com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler"/>
        

    </resultMap>

  <select id="listDeviceReportInformation" resultMap="DmpDeviceReportResult">
        select trace_id, imei, topic, information, interaction_time,type
        from dmp_device_report_information
        where imei = #{serialNumber}
        <if test="beginTime != null and endTime != null">
            and interaction_time between #{beginTime} and #{endTime}
        </if>
        <if test="traceId != null and traceId != ''">
            and trace_id = #{traceId}
        </if>
        limit #{pageSize}  offset #{pageNum}
    </select>

新增

<insert id="add" parameterType="com.chinaunicom.iotdb.domain.DmpDeviceReportInformation">
        INSERT INTO root.device.dmp_device_report_information
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="null != type ">
                type,
            </if>
            <if test="null != traceId and '' != traceId">
                trace_id,
            </if>
            <if test="null != imei and '' != imei">
                imei,
            </if>
            <if test="null != topic and '' != topic">
                topic,
            </if>
            <if test="null != information and '' != information">
                information,
            </if>
            <if test="null != interactionTime  and '' != interactionTime ">
                interaction_time,
            </if>
            <if test="null != organizationId ">
                organization_id
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="null != type ">
                #{type,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
            <if test="null != traceId and '' != traceId">
                #{traceId,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
            <if test="null != imei and '' != imei">
                #{imei,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
            <if test="null != topic and '' != topic">
                #{topic,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
            <if test="null != information and '' != information">
                #{information,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
            <if test="null != interactionTime and '' != interactionTime ">
                #{interactionTime,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
            <if test="null != organizationId ">
                #{organizationId,typeHandler=com.chinaunicom.iotdb.handler.JsonIntegerTypeHandler },
            </if>
        </trim>
    </insert>

mybatisPlus中使用

类注解 @TableName(autoResultMap = true)

参数注解 @TableField(typeHandler = JsonIntegerTypeHandler.class)

@Data
@TableName(autoResultMap = true)
public class DmpDeviceReportInformation implements Serializable
{
    private static final long serialVersionUID = 1L;

    private Long id;

    /**
     * 消息类型1:消息上报 2:消息下发
     */
 @TableField(typeHandler = JsonIntegerTypeHandler.class)
    private Integer type;
    }

注意: 如果使用自己的mapper查询 要选择mybaits的形式

要想全局生效的话

mybatis-plus:
   type-handlers-package: com.chinaunicom.iotdb.handler
相关推荐
Elastic 中国社区官方博客23 分钟前
使用 Elasticsearch 导航检索增强生成图表
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
小金的学习笔记27 分钟前
RedisTemplate和Redisson的使用和区别
数据库·redis·缓存
新知图书42 分钟前
MySQL用户授权、收回权限与查看权限
数据库·mysql·安全
文城5211 小时前
Mysql存储过程(学习自用)
数据库·学习·mysql
沉默的煎蛋1 小时前
MyBatis 注解开发详解
java·数据库·mysql·算法·mybatis
呼啦啦啦啦啦啦啦啦1 小时前
【Redis】事务
数据库·redis·缓存
HaoHao_0101 小时前
AWS Serverless Application Repository
服务器·数据库·云计算·aws·云服务器
C语言扫地僧1 小时前
MySQL 事务及MVCC机制详解
数据库·mysql
小镇cxy1 小时前
MySQL事物,MVCC机制
数据库·mysql
书生-w2 小时前
Redis Windows 解压版安装
数据库·windows·redis