MyBatis Plus:自定义typeHandler类型处理器

2024-02-21 17:12

本文主要是介绍MyBatis Plus:自定义typeHandler类型处理器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

引言:关于TypeHandler

PostGreSQL:JSON数据类型

PostGreSQL数据库驱动:PGobject类

TypeHandler类型处理器

自定义类型处理器

类型处理器实现:PGJsonTypeHandler

注册类型处理器


引言:关于TypeHandler

        MyBatis Plus提供了丰富的类型处理器TypeHandler,用于实现用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值。

        但是,内置的类型处理器在某些特殊情况难以满足实际开发需求。以下,以PostGreSQL数据库中的JSON类型为例,叙述自定义类型处理器,实现java.util.Map与PostGreSQL中JSON类型之间的转换。

PostGreSQL:JSON数据类型

        使用SQL语句构建JSON类型字段值是十分简单的,

-- 简单标量/基本值
-- 基本值可以是数字、带引号的字符串、true、false或者null
SELECT '5'::json;-- 有零个或者更多元素的数组(元素不需要为同一类型)
SELECT '[1, 2, "foo", null]'::json;-- 包含键值对的对象
-- 注意对象键必须总是带引号的字符串
SELECT '{"bar": "baz", "balance": 7.77, "active": false}'::json;-- 数组和对象可以被任意嵌套
SELECT '{"foo": [true, "bar"], "tags": {"a": 1, "b": null}}'::json;

        问题在于:如何将java中的Map类型转换为PG数据库中的JSON字段值。

PostGreSQL数据库驱动:PGobject类

        在PostGreSQL数据库驱动依赖包的org.postgresql.util工具包下,挖出来了一个名称为:PGobject的类,

        该类(PGobject)的源码描述信息如下:

PGobject is a class used to describe unknown types An unknown type is any type that is unknown by JDBC Standards.

概略含义:PGobject是一个用于描述一种非JDBC标准的未知类型。

        可以看到,它内置了很多子类,用于描述PostGreSQL中的Line、Polygon、Money等数据类型。

         一通分析之后,发现PGobject类的type、value属性是比较重要的(毕竟只提供了这两个属性),

        查看源码之后,解读type和value字段的含义:

type:object对象的类型,

value:object对象的值。

        再拿来和PGpolygon子类做一下对比,会发现:type属性其实就是一个String字符串,用于描述PostGreSQL内置数据类型的名称;value则是具体的值。那么,我们也可以借助这个PGobject类来描述自己的类型。

TypeHandler类型处理器

        TypeHandler类型处理器是MyBatis/MyBatisPlus很重要的一部分内容,日常开发中,从数据表到JavaBean,从JavaBean到数据表,两者之间的转换全靠这些内置的TypeHandler来实现。

        查看TypeHandler的源码,内容如下,

/*** @author Clinton Begin*/
public interface TypeHandler<T> {void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;/*** Gets the result.** @param rs*          the rs* @param columnName*          Column name, when configuration <code>useColumnLabel</code> is <code>false</code>* @return the result* @throws SQLException*           the SQL exception*/T getResult(ResultSet rs, String columnName) throws SQLException;T getResult(ResultSet rs, int columnIndex) throws SQLException;T getResult(CallableStatement cs, int columnIndex) throws SQLException;}

        可以分为两类,其中:

①setParameter:是将JavaBean属性值转换为PostGreSQL支持的数据库字段值;

②3个getResult方法:熟悉原生JDBC编程的朋友应该都很眼熟,其实就是通过PreparedStatement执行完SQL之后,对ResultSet结果集进行按字段名columnName、按索引下标columnIndex,将PostGreSQL支持的数据库字段值,转换为JavaBean属性值的过程。

自定义类型处理器

        了解了上述内容之后,我们要自定义类型处理器,核心的工作就是:对TypeHandler接口提供的三个方式进行实现。

类型处理器实现:PGJsonTypeHandler

        以下给出一个Map集合类型到PostGreSQL-JSON数据类型之间的转换器实现类,相关部分可以直接查看代码注释,

/*** TypeHandler:类型处理器,用于 JavaType 与 JdbcType 之间的转换*  [1] 用于 PreparedStatement 设置参数值*  [2] 用于从 ResultSet CallableStatement 中取出一个值* PGJsonTypeHandler:处理Map集合类型与postgresql中JSON类型之间的转换*/@MappedTypes(value = {Object.class})
public class PGJsonTypeHandler<T> extends BaseTypeHandler<T> {//PGobject:PGobject is a class used to describe unknown types An unknown type is any type that is unknown by JDBC Standards.private static final PGobject pgObject = new PGobject();/*** 插入时设置参数类型* @param preparedStatement SQL预编译对象* @param i 需要赋值的索引位置(相当于在JDBC中对占位符的位置进行赋值)* @param parameter 索引位置i需要赋的值(原本要给这个位置赋的值,在setNonNullParameter方法中主要解决的问题就是将这个自定义类型变成数据库认识的类型)* @param jdbcType jdbc的类型* @throws SQLException*/@Overridepublic void setNonNullParameter(PreparedStatement preparedStatement, int i, T parameter, JdbcType jdbcType) throws SQLException {if (preparedStatement != null) {System.out.println("setNonNullParameter::"+parameter.toString());pgObject.setType("json");pgObject.setValue(JSON.toJSONString(parameter));preparedStatement.setObject(i, pgObject);}}/*** 转换为T类型实例* @param object 参数字符串({"name":"张三","age":18,"address":"北京市朝阳区"})或者null空值* @return T实例或者参数*/private T parseAsTInstance(Object object){//判空if(object == null){return null;}//处理字符串{"name":"张三","age":18,"address":"北京市朝阳区"}-转换为Map类型Map map = JSON.parseObject(object.toString(), Map.class);return (T)map;}/*** 获取时转换回的自定义类型* @param resultSet 结果集* @param s 列名称* @return Bean对象*/@Overridepublic T getNullableResult(ResultSet resultSet, String s) throws SQLException {Object object = resultSet.getObject(s);return parseAsTInstance(object);}/*** 获取时转换回的自定义类型* @param resultSet 结果集* @param i 列索引*/@Overridepublic T getNullableResult(ResultSet resultSet, int i) throws SQLException {Object object = resultSet.getObject(i);return parseAsTInstance(object);}/*** 获取时转换回的自定义类型* @param callableStatement 结果集* @param i 列索引*/@Overridepublic T getNullableResult(CallableStatement callableStatement, int i) throws SQLException {Object object = callableStatement.getObject(i);return parseAsTInstance(object);}
}

注册类型处理器

        要注册类型处理器,可以进行全局配置:typeHandlersPackage属性

        也可以在局部直接使用,例如:

package com.example.soil_backend.model.entity;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;import java.time.LocalDateTime;import com.baomidou.mybatisplus.annotation.TableId;import java.io.Serializable;
import java.util.Map;import com.example.soil_backend.model.TbBase;
import com.example.soil_backend.typehandler.PGJsonbTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;/*** 配置模板** @author XiMumu* @since 2024-02-18*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName(value = "tb_template", autoResultMap = true)
public class TbTemplate extends TbBase implements Serializable {private static final long serialVersionUID = -2288822970791637243L;/*** 主键ID*/@TableId(value = "id", type = IdType.AUTO)private Integer id;/*** 调查模板名称*/@TableField(value = "name")private String name;/*** 模板配置JSON*/@TableField(value = "config",typeHandler = PGJsonbTypeHandler.class)private Map config;/*** 是否删除:1-使用中;2-已删除*/@TableField(value = "del_flag")private Integer delFlag;}

      

这篇关于MyBatis Plus:自定义typeHandler类型处理器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/732493

相关文章

在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码

《在MyBatis的XML映射文件中<trim>元素所有场景下的完整使用示例代码》在MyBatis的XML映射文件中,trim元素用于动态添加SQL语句的一部分,处理前缀、后缀及多余的逗号或连接符,示... 在MyBATis的XML映射文件中,<trim>元素用于动态地添加SQL语句的一部分,例如SET或W

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

Mybatis官方生成器的使用方式

《Mybatis官方生成器的使用方式》本文详细介绍了MyBatisGenerator(MBG)的使用方法,通过实际代码示例展示了如何配置Maven插件来自动化生成MyBatis项目所需的实体类、Map... 目录1. MyBATis Generator 简介2. MyBatis Generator 的功能3

Mybatis提示Tag name expected的问题及解决

《Mybatis提示Tagnameexpected的问题及解决》MyBatis是一个开源的Java持久层框架,用于将Java对象与数据库表进行映射,它提供了一种简单、灵活的方式来访问数据库,同时也... 目录概念说明MyBATis特点发现问题解决问题第一种方式第二种方式问题总结概念说明MyBatis(原名

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题

《解决mybatis-plus-boot-starter与mybatis-spring-boot-starter的错误问题》本文主要讲述了在使用MyBatis和MyBatis-Plus时遇到的绑定异常... 目录myBATis-plus-boot-starpythonter与mybatis-spring-b

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

Spring Boot 中整合 MyBatis-Plus详细步骤(最新推荐)

《SpringBoot中整合MyBatis-Plus详细步骤(最新推荐)》本文详细介绍了如何在SpringBoot项目中整合MyBatis-Plus,包括整合步骤、基本CRUD操作、分页查询、批... 目录一、整合步骤1. 创建 Spring Boot 项目2. 配置项目依赖3. 配置数据源4. 创建实体类

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景