当前位置: 首页 > news >正文

【第25章】MyBatis-Plus之字段类型处理器

文章目录

  • 前言
  • 一、JSON 字段类型处理器
    • 1. 配置
    • 2. XML 配置对应写法
    • 3. Wrapper 查询中的 TypeHandler 使用
  • 二、自定义类型处理器
    • 1. 创建自定义类型处理器
    • 2. 使用自定义类型处理器
  • 三、实战
    • 1. 实体类
    • 2. 测试类
    • 3. 测试结果
  • 总结


前言

在 MyBatis 中,类型处理器(TypeHandler)扮演着 JavaTypeJdbcType 之间转换的桥梁角色。它们用于在执行 SQL 语句时,将 Java 对象的值设置到 PreparedStatement 中,或者从 ResultSetCallableStatement 中取出值。

MyBatis-Plus 给大家提供了提供了一些内置的类型处理器,可以通过 TableField 注解快速注入到 MyBatis 容器中,从而简化开发过程。

示例工程:👉 mybatis-plus-sample-typehandler


一、JSON 字段类型处理器

MyBatis-Plus 内置了多种 JSON 类型处理器,包括 AbstractJsonTypeHandler 及其子类 Fastjson2TypeHandlerFastjsonTypeHandlerGsonTypeHandlerJacksonTypeHandler 等。这些处理器可以将 JSON 字符串与 Java 对象相互转换。

1. 配置

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {private Long id;.../*** 必须开启映射注解** @TableName(autoResultMap = true)** 选择对应的 JSON 处理器,并确保存在对应的 JSON 解析依赖包*/@TableField(typeHandler = JacksonTypeHandler.class)// 或者使用 FastjsonTypeHandler// @TableField(typeHandler = FastjsonTypeHandler.class)private OtherInfo otherInfo;
}

2. XML 配置对应写法

在 XML 映射文件中,可以使用 <result> 元素来指定字段的类型处理器。

<!-- 单个字段的类型处理器配置 -->
<result column="other_info" jdbcType="VARCHAR" property="otherInfo" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" /><!-- 多个字段中某个字段的类型处理器配置 -->
<resultMap id="departmentResultMap" type="com.baomidou...DepartmentVO"><result property="director" column="director" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />
</resultMap>
<select id="selectPageVO" resultMap="departmentResultMap">select id,name,director from department ...
</select>

3. Wrapper 查询中的 TypeHandler 使用

从 MyBatis-Plus 3.5.3.2 版本开始,可以在 Wrapper 查询中直接使用 TypeHandler

Wrappers.<H2User>lambdaQuery().apply("name={0,typeHandler=" + H2userNameJsonTypeHandler.class.getCanonicalName() + "}", "{\"id\":101,\"name\":\"Tomcat\"}"))

通过上述示例,你可以看到 MyBatis-Plus 提供了灵活且强大的类型处理器支持,使得在处理复杂数据类型时更加便捷。在使用时,请确保选择了正确的 JSON 处理器,并引入了相应的 JSON 解析库依赖。

二、自定义类型处理器

在 MyBatis-Plus 中,除了使用内置的类型处理器外,开发者还可以根据需要自定义类型处理器。

例如,当使用 PostgreSQL 数据库时,可能会遇到 JSONB 类型的字段,这时可以创建一个自定义的类型处理器来处理 JSONB 数据。

以下是一个自定义的 JSONB 类型处理器的示例:

1. 创建自定义类型处理器

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.postgresql.util.PGobject;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class JsonbTypeHandler<T> extends BaseTypeHandler<T> {private final Class<T> clazz;public JsonbTypeHandler(Class<T> clazz) {if (clazz == null) {throw new IllegalArgumentException("Type argument cannot be null");}this.clazz = clazz;}@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {PGobject jsonbObject = new PGobject();jsonbObject.setType("jsonb");jsonbObject.setValue(JsonUtils.toJsonString(parameter)); // 假设 JsonUtils 是一个用于 JSON 序列化的工具类ps.setObject(i, jsonbObject);}@Overridepublic T getNullableResult(ResultSet rs, String columnName) throws SQLException {return parseJsonb(rs.getString(columnName));}@Overridepublic T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return parseJsonb(rs.getString(columnIndex));}@Overridepublic T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return parseJsonb(cs.getString(columnIndex));}private T parseJsonb(String jsonbString) {if (jsonbString != null) {return JsonUtils.parseObject(jsonbString, clazz); // 假设 JsonUtils 是一个用于 JSON 反序列化的工具类}return null;}
}

2. 使用自定义类型处理器

在实体类中,通过 TableField 注解指定自定义的类型处理器:

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {private Long id;.../*** 使用自定义的 JSONB 类型处理器*/@TableField(typeHandler = JsonbTypeHandler.class)private OtherInfo otherInfo;
}

通过上述步骤,你可以在 MyBatis-Plus 中使用自定义的 JSONB 类型处理器来处理 PostgreSQL 数据库中的 JSONB 类型字段。自定义类型处理器提供了极大的灵活性,使得开发者可以根据具体的数据库特性和业务需求来定制数据处理逻辑。

三、实战

1. 实体类

package org.example.springboot3.mybatisplus.model;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.example.springboot3.mybatisplus.enums.GenderEnum;
import org.example.springboot3.mybatisplus.enums.StatusEnum;
import java.io.Serializable;
import java.time.LocalDateTime;/*** Create by zjg on 2024/6/27*/
@Getter
@Setter
@ToString
@TableName(value="user1",autoResultMap = true)
@NoArgsConstructor
public class User {@TableId(type= IdType.AUTO)private Long id;private String name;private Integer age;private String email;private GenderEnum gender;private StatusEnum status;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.UPDATE)private LocalDateTime updateTime;@TableLogic@TableField(fill = FieldFill.INSERT)private Integer deleted;/*** 必须开启映射注解** @TableName(autoResultMap = true)** 选择对应的 JSON 处理器,并确保存在对应的 JSON 解析依赖包*/@TableField(typeHandler = JacksonTypeHandler.class)private OtherInfo otherInfo;public User(String name) {this.name = name;}public User(Long id, String name) {this.id = id;this.name = name;}public User(String name, int age) {this.name=name;this.age=age;}public User(long id, String name, int age) {this.id=id;this.name=name;this.age=age;}@Getter@Setter@NoArgsConstructor@AllArgsConstructor@ToStringpublic static class OtherInfo implements Serializable {@TableId(type= IdType.AUTO)private Long id;private String name;}
}

2. 测试类

package org.example.springboot3.mybatisplus.controller;import org.example.springboot3.mybatisplus.model.User;
import org.example.springboot3.mybatisplus.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Create by zjg on 2024/7/6*/
@RestController
@RequestMapping("/type-handler/")
public class TypeHandlerController {@AutowiredUserService userService;@PostMappingpublic void save() {// 假设有一个 User 实体对象User user = new User();user.setName("zhangzhiwei");user.setEmail("zhangzhiwei@lhs.com");user.setOtherInfo(new User.OtherInfo(1L,"张天师"));boolean result = userService.save(user); // 调用 save 方法if (result) {System.out.println("User saved successfully.");} else {System.out.println("Failed to save user.");}}@GetMappingpublic void get(int id) {// 假设要查询 ID 为 1 的用户User user = userService.getById(id); // 调用 getById 方法if (user != null) {System.out.println("User found: " + user);} else {System.out.println("User not found.");}}
}

3. 测试结果

save

[2024-07-06 19:38:08.964][http-nio-8080-exec-1][DEBUG]- org.example.springboot3.mybatisplus.util.StdoutLogger.logText(StdoutLogger.java:13) -  Consume Time:7 ms 2024-07-06 19:38:08Execute SQL:INSERT INTO user1 ( name, email, create_time, deleted, other_info ) VALUES ( 'zhangzhiwei', 'zhangzhiwei@lhs.com', '2024-07-06T19:38:08.891290800', 0, '{"id":1,"name":"张天师"}' )
[2024-07-06 19:38:08.964][http-nio-8080-exec-1][DEBUG]- org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:135) - <==    Updates: 1
User saved successfully.

get

[2024-07-06 19:45:04.816][http-nio-8080-exec-1][DEBUG]- org.example.springboot3.mybatisplus.util.StdoutLogger.logText(StdoutLogger.java:13) -  Consume Time:2 ms 2024-07-06 19:45:04Execute SQL:SELECT id,name,age,email,gender,status,create_time,update_time,deleted,other_info FROM user1 WHERE id=1120071 AND deleted=0
[2024-07-06 19:45:04.886][http-nio-8080-exec-1][DEBUG]- org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:135) - <==      Total: 1
User found: User(id=1120071, name=zhangzhiwei, age=null, email=zhangzhiwei@lhs.com, gender=null, status=null, createTime=2024-07-06T19:38:09, updateTime=null, deleted=0, otherInfo=User.OtherInfo(id=1, name=张天师))

总结

回到顶部

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C#中的集合
  • 提高LabVIEW软件的健壮性
  • 南方科技大学马永胜教授给年轻人使用AI工具上的建议
  • 教师管理小程序的设计
  • 机器视觉/自然语言/生成式人工智能综合应用实验平台-实训平台-教学平台
  • Qt QChart 图表库详解及使用
  • Linux调试器-gdb使用以及Linux项目自动化构建工具-make/Makefile
  • 三级_网络技术_11_路由设计技术基础
  • 今年嵌入式行情怎么样?
  • PHP禁止IP访问和IP段访问(代码实例)
  • Git的稀疏检出(sparse checkout)
  • eclipse ide中文件编码的修改,解决中文乱码的问题。
  • 独立开发者系列(23)——Linux掌握小结
  • websockt初始化,创建一个webSocket示例
  • 安装Go语言常用工具
  • 时间复杂度分析经典问题——最大子序列和
  • 【5+】跨webview多页面 触发事件(二)
  • 3.7、@ResponseBody 和 @RestController
  • avalon2.2的VM生成过程
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • Iterator 和 for...of 循环
  • React Transition Group -- Transition 组件
  • React-redux的原理以及使用
  • webpack项目中使用grunt监听文件变动自动打包编译
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 使用common-codec进行md5加密
  • 自动记录MySQL慢查询快照脚本
  • 你对linux中grep命令知道多少?
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​用户画像从0到100的构建思路
  • #if #elif #endif
  • #微信小程序(布局、渲染层基础知识)
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (19)夹钳(用于送货)
  • (2)空速传感器
  • (3)STL算法之搜索
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (PySpark)RDD实验实战——取最大数出现的次数
  • (不用互三)AI绘画工具应该如何选择
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (学习日记)2024.01.19
  • (译)2019年前端性能优化清单 — 下篇
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)shell调试方法
  • (转)关于多人操作数据的处理策略
  • (转载)OpenStack Hacker养成指南
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • . NET自动找可写目录
  • .net 8 发布了,试下微软最近强推的MAUI
  • .net core docker部署教程和细节问题
  • .net core开源商城系统源码,支持可视化布局小程序