前言
对于某些场景,数据库存储的是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>