Mybatisplus字段类型处理器的使用

840 阅读3分钟

前言

对于某些场景,数据库存储的是json,但是在java里面可能是一个对象,以前的处理我们习惯称一个对象对应一个表,面对这种场景要如何处理呢,其实这时mybatisplus的字段转换器就派上用场了。

mybatisplus字段类型处理器

官网上的介绍baomidou.com/pages/fd41d…

类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值

意思就是java中类型个数据库的存储在mybatisplus中是需要转换的,而这个转换任务就是由类型转换器来完成的

mybatisplus字段类型处理器使用

场景:定时任务要扫描表中的任务数据,其中一个字段在java中定义为一个对象,但是存入数据库中为jason格式

实体类:

@NoArgsConstructor
@Builder
@AllArgsConstructor
@Accessors(chain = true)
@TableName(value = "contract_lease_order_job_record", autoResultMap = true)
public class ContractLeaseOrderJobRecord {
    /**
     * 主键id
     */
    @TableField("id")
    private Long id;

    /**
     * 当前任务剩余数量
     */
    private Integer num;

    /**
     * 数据基础
     */
    @TableField(typeHandler = GenericTypeHandler.class)
    private OrderContractLeaseDTO data;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 创建人
     **/
    private Long creatorId;

    /**
     * 创建人名称
     **/
    private String creatorName;

    /**
     * 创建人真实名称
     **/
    private String creatorRealName;

    /**
     * 执行任务状态
     * 0 未执行
     * 1 已执行
     * 2 执行失败
     **/
    private Integer executionStatus;
}




package com.example.w_spring_demo.entity;

import com.example.w_spring_demo.helper.ValidateGroupLeaseOrderExtend;
import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.List;


@Data
public class OrderContractLeaseDTO {

    /**
     * 分裂数量
     */
    private Integer num;

    /**
     * 任务校验码
     */
    private String checkCode;

    /**
     * 基础
     **/
    @Valid
    private ParentOrderBasic parentOrderBasic;

    /**
     * 子订单商品
     **/
    @Valid
    private List<ParentOrderGoods> parentOrderGoodsList;

    /**
     * 业务人员归属
     **/
    @Valid
    private List<ParentOrderSaleman> parentOrderSalemans;

    /**
     * 客户信息
     */
    @Valid
    private ParentOrderCustomer parentOrderCustomer;


    /**
     * 合同信息
     */
    @Valid
    private ParentOrderContract parentOrderContract;

    /**
     * 结算信息
     */
    private ParentOrderSettlement parentOrderSettlement;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 创建人id
     */
    private Long creatorId;

    /**
     * 创建人名称
     */
    private String creatorName;

    /**
     * 创建人真实名称
     */
    private String creatorRealName;
}

mapper文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.w_spring_demo.mapper.plan.LeaseOrderPlanMapper">

    <resultMap id="OrderGeneralLeaseMap"
               type="com.example.w_spring_demo.entity.ContractLeaseOrderJobRecord">
        <id column="id" property="id"/>
    </resultMap>

    <insert id="save"
            parameterType="com.example.w_spring_demo.entity.ContractLeaseOrderJobRecord">
        INSERT INTO contract_lease_order_job_record (
            num,
            check_code,
            data,
            create_time,
            creator_id,
            creator_name
        )SELECT * FROM (
                SELECT
                    #{data.num}         AS 0L,
                    #{data.checkCode}   AS 1L,
                    #{data}             AS 2L,
                    #{data.createTime}  AS 3L,
                    #{data.creatorId}   AS 4L,
                    #{data.creatorName} AS 5L
                FROM dual
        )s
        WHERE NOT EXISTS (
                SELECT
                    1
                FROM
                    contract_lease_order_job_record t
                WHERE
                    t.num > 0 AND t.check_code = #{data.checkCode}
            );
    </insert>



    <select id="countPagePlanList" resultType="java.lang.Long">
        SELECT COUNT(1) FROM contract_lease_order_job_record WHERE  num > 0 and execution_status = 0
    </select>

</mapper>

类型转换器:

package com.example.w_spring_demo.mybatisplus;

import com.example.w_spring_demo.entity.OrderContractLeaseDTO;
import com.example.w_spring_demo.helper.JsonUtil;
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 org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;

/**
 * @Description: 新增类型自动适配mybatis json序列化转换配置
 * 非object类型适配指定 原因 显示指定类型,简化typehandler mybatis xml中的显示配置
 * @Date: 2022/2/10 13:56
 */


@MappedTypes({OrderContractLeaseDTO.class})
public class GenericTypeHandler<T> extends BaseTypeHandler<T> {

    private final Class<T> type;

    public GenericTypeHandler(Class<T> type) {
        Assert.isTrue(Objects.nonNull(type), "新增类型自动适配mybatis json序列化转换配置 类型不可为空");
        this.type = type;
    }

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

    @Override
    public T getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        String data = rs.getString(columnName);
        return JsonUtil.toBean(data, type);
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String data = rs.getString(columnIndex);
        return JsonUtil.toBean(data, type);
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        String data = cs.getString(columnIndex);
        return JsonUtil.toBean(data, type);
    }
}

类型转换器中的代码就是将对象转换成json,查询时json转换成对象,其实就是本文开头时说的字段类型转换器的作用,其实只有这些还是不能实现类型转换,还是要加配置

配置文件:

mybatis-plus.configuration.auto-mapping-unknown-column-behavior=WARNING
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.mapper-locations=classpath*:mapper/plan/*.xml
mybatis-plus.type-handlers-package=com.example.w_spring_demo.mybatisplus

如果小伙伴也自己写代码并且跑起来了,那么恭喜你,成功解锁了一项功能,如果到这里还没有成功,那么你可能遇到和我一样的问题,这个问题困扰了我很久,我在进行完这部分配置后,启动报错,type-handlers-package 不生效,百思不得其解,后来发现原来时mybatisplus版本的问题,改成3.5.0问题终于解决了,而我之前的版本时3.3.1,这种问题真的很难排查......

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.0</version>
        </dependency>