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

相关文章

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取

MyBatis-Plus 自动赋值实体字段最佳实践指南

《MyBatis-Plus自动赋值实体字段最佳实践指南》MyBatis-Plus通过@TableField注解与填充策略,实现时间戳、用户信息、逻辑删除等字段的自动填充,减少手动赋值,提升开发效率与... 目录1. MyBATis-Plus 自动赋值概述1.1 适用场景1.2 自动填充的原理1.3 填充策略

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

mybatis中resultMap的association及collectio的使用详解

《mybatis中resultMap的association及collectio的使用详解》MyBatis的resultMap定义数据库结果到Java对象的映射规则,包含id、type等属性,子元素需... 目录1.reusltmap的说明2.association的使用3.collection的使用4.总

mybatis-plus QueryWrapper中or,and的使用及说明

《mybatis-plusQueryWrapper中or,and的使用及说明》使用MyBatisPlusQueryWrapper时,因同时添加角色权限固定条件和多字段模糊查询导致数据异常展示,排查发... 目录QueryWrapper中or,and使用列表中还要同时模糊查询多个字段经过排查这就导致只要whe

SpringBoot集成MyBatis实现SQL拦截器的实战指南

《SpringBoot集成MyBatis实现SQL拦截器的实战指南》这篇文章主要为大家详细介绍了SpringBoot集成MyBatis实现SQL拦截器的相关知识,文中的示例代码讲解详细,有需要的小伙伴... 目录一、为什么需要SQL拦截器?二、MyBATis拦截器基础2.1 核心接口:Interceptor

SpringBoot改造MCP服务器的详细说明(StreamableHTTP 类型)

《SpringBoot改造MCP服务器的详细说明(StreamableHTTP类型)》本文介绍了SpringBoot如何实现MCPStreamableHTTP服务器,并且使用CherryStudio... 目录SpringBoot改造MCP服务器(StreamableHTTP)1 项目说明2 使用说明2.1

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口