MyBatis-Plus 三、(进阶使用)

news2024/9/28 23:33:14

一、typeHandler 的使用

   1、存储json格式字段

        如果字段需要存储为json格式,可以使用JacksonTypeHandler处理器。使用方式非常简单,如下所示:
        

        只需要加上两个注解即可:
         @TableName(autoResultMap = true) 表示自动映射resultMap
         @TableField(typeHandler = JacksonTypeHandler.class)表示将UserInfo对象转为json对象入库

        2、自定义 typeHandler 实现类

        例如当我们 某个字段存储的类型为List或者Map时,我们可以自定义一个TypeHandler,以 list 为例,我们想存储一个字段类型为 list ,在数据库中的存储的格式是 多条数据以逗号分割,当查询时会自动根据逗号分割成列表格式。

        需要实现BaseTypeHandler抽象类:

@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes({List.class})
public class ListTypeHandler extends BaseTypeHandler<List<String>> {

    private static final String DELIM = ",";

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
        String value = StringUtils.collectionToDelimitedString(strings, DELIM);
        preparedStatement.setString(i, value);
    }

    @Override
    public List<String> getNullableResult(ResultSet resultSet, String s) throws SQLException {
        String value = resultSet.getString(s);
        return Arrays.asList(StringUtils.tokenizeToStringArray(value, DELIM));
    }

    @Override
    public List<String> getNullableResult(ResultSet resultSet, int i) throws SQLException {
        String value = resultSet.getString(i);
        return Arrays.asList(StringUtils.tokenizeToStringArray(value, DELIM));
    }

    @Override
    public List<String> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        String value = callableStatement.getString(i);
        return Arrays.asList(StringUtils.tokenizeToStringArray(value, DELIM));
    }
}
  • @MappedJdbcTypes:表示SQL语句中查出来的类型;
  • @MappedTypes:表示要转成 Java 对象的类型;
  • DELIM:表示字符串的分隔符,如果你是用空格分开的就赋值为空格。
  • setNonNullParameter(插入时设置参数类型)

  • getNullableResult(获取时转换回的自定义类型)

        根据列名获取

resultSet:结果集
columnName:列名
public UserInfo getNullableResult(ResultSet resultSet, String columnName)

        根据索引位置获取

resultSet:结果集
columnIndex:列索引
public UserInfo getNullableResult(ResultSet resultSet, int columnIndex)

        根据存储过程获取 

callableStatement:结果集
columnIndex:列索引
public UserInfo getNullableResult(CallableStatement callableStatement, int columnIndex)

        然后再字段上指定该实现了即可:

    @TableField(typeHandler = ListTypeHandler.class)
    private List<String> job;

        最后在数据库中存储格式为:  

 

 

        3、存储自定义对象字段

        例如我们刚才使用json格式存储 Unit 字段,如果不加  @TableField(typeHandler = JacksonTypeHandler.class) 就会报错,因为 typeHandler 可以指定我们在Java实体类所包含的自定义类型存入数据库后的类型是什么,也可以从数据库中取出该数据后自动转换为我们自定义的Java类型。

        我们虽然在 Java中定义了 Unit 类型,但是数据库不认识,我们现在就需要将 Unit 转换为数据库认识的类型。Java自带的类型在存取的时候不会出错,我们自定义的类型就会出错 是因为 mybatis已经将这些类型的TypeHandler提前写好了:
                   

         所以如果我们要存储 Unit 类型的字段,又不想用 默认的json 格式,我们也需要自定义一个 关于Unit 的 TypeHandler,如下:

public class JsonUtils {
    private static ObjectMapper objectMapper = new ObjectMapper();

    //初始化相关的配置
    static {
        //只引用不为空的值
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);

        //取消默认转换timestemp
        objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);

        //忽略空bean转换错误
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

        //忽略在json中存在,在java对象不存在的错误
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 解决jackson2无法反序列化LocalDateTime的问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
    }

    /**
     * 将java对象转换成json字符串
     *
     * @param obj
     * java 对象
     * @param <T>
     * @return
     */
    public static <T> String objectToString(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将json字符串转换成java对象
     *
     * @param json
     * 字符串
     * @param tClass
     * 要转换的对象
     * @param <T>
     * @return
     */
    public static <T> T getObjetFormString(String json, Class<T> tClass) {
        if (StringUtils.isBlank(json) || tClass == null) {
            return null;
        }

        try {
            return tClass.equals(String.class) ? (T) json : objectMapper.readValue(json, tClass);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将字符串转换成java对象
     * @param json
     * 字符串
     * @param tTypeReference
     * 对象
     *
     * @param <T>
     * @return
     */
    public static <T> T fromString(String json, TypeReference<T> tTypeReference){
        if (StringUtils.isBlank(json) || tTypeReference == null) {
            return null;
        }

        try {
            return tTypeReference.getType().equals(String.class) ? (T) json : objectMapper.readValue(json, tTypeReference);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将json字符串转换成java集合对象
     * @param json
     * 字符串
     * @param collectionClass
     * 集合类型
     * @param elementClazzes
     * 成员类型
     * @param <T>
     * @return
     */
    public static <T> T fromString(String json, Class<?> collectionClass, Class<?> ... elementClazzes){
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClazzes);
        try {
            return objectMapper.readValue(json, javaType);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}
@MappedTypes(UserInfo.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class UserInfoTypeHandler extends BaseTypeHandler<UserInfo> {

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, UserInfo userInfo, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i,  JsonUtils.objectToString(userInfo));
    }

    @Override
    public UserInfo getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        return JsonUtils.fromString(resultSet.getString(columnName),UserInfo.class);
    }

    @Override
    public UserInfo getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return JsonUtils.fromString(resultSet.getString(columnIndex),UserInfo.class);
    }

    @Override
    public UserInfo getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return 
 JsonUtils.fromString(callableStatement.getString(columnIndex),UserInfo.class);
    }
}

        其实还是将该对象转成了 json ,但是只不过转成 json 的工具类可以 由我们自己指定。

二、mybatisplus 存储枚举类型

        存储枚举类型有两种形式,第一种就是自定义  typeHandler 跟上面一样,还有一种是使用mybatis提供的默认的处理类,如下所所示:

        数据库表结构:


         mybatisPlus对枚举处理器进行了补充:


        创建枚举类:

@Getter
public enum OrderState {
    NORMAL(0, "正常"),
    CANCEL(1, "取消"),
    DELETE(2, "删除");
 
    // 状态码
    @EnumValue // 用于数据库存储
    private Integer code;
    // 描述
    @JsonValue // 用于序列化返回的json数据
    private String desc;
 
    OrderState(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }
 
}


        TOrder实体类:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_order")
public class TOrder implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @TableId(value = "order_id", type = IdType.AUTO)
    private Integer orderId;
 
    @TableField("user_id")
    private Integer userId;
 
    @TableField("price")
    private BigDecimal price;
 
    @TableField("status")
    private OrderState status;
 
}


在配置文件中配置统一的枚举处理器,实现类型转换:

        调用:

三、使用CommandLineRunner 修改 JacksonTypeHandler 实现类

@Component
public class JsonTypeHandlerConfig implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        JacksonTypeHandler.setObjectMapper(JsonUtils.getMapper());
    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2066760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Instrumentation创建代理程序监测Java对象信息

文章目录 创建代理使用代理监测测试代码运行配置运行效果 总结 Instrumentation 是Java提供的一种能够在程序运行时检查和修改类定义的技术。使用Instrumentation&#xff0c;可以构建一个独立于应用程序的代理程序&#xff0c;检测和协助运行在JVM上的程序&#xff0c;甚至可以…

Netty03-进阶

三. Netty 进阶 1. 粘包与半包 1.1 粘包现象 服务端代码 public class HelloWorldServer {static final Logger log LoggerFactory.getLogger(HelloWorldServer.class);void start() {NioEventLoopGroup boss new NioEventLoopGroup(1);NioEventLoopGroup worker new Ni…

高性能4G灯杆网关,未来智慧城市的神经中枢

在智慧城市的建设浪潮中&#xff0c;灯杆作为城市基础设施的重要组成部分&#xff0c;正在经历一场革命性的转变。SG600 4G灯杆网关就是这场革命的核心产品&#xff0c;它将普通的路灯转变为集照明、监控、通信、环境监测等多功能于一体的智慧终端。 产品优势&#xff1a; 高度…

[图解]分析工作流开始01

1 00:00:02,650 --> 00:00:04,200 需求工作流结束之后 2 00:00:04,610 --> 00:00:06,880 我们就要进入分析工作流了 3 00:00:07,890 --> 00:00:09,020 在分析工作流里面 4 00:00:09,030 --> 00:00:13,060 我们使用类图、序列图 5 00:00:13,710 --> 00:00:16…

深度学习入门-03

PS&#xff1a;基于小土堆视频学习https://www.bilibili.com/video/BV1hE411t7RN?p6&vd_source22926f91481026cd10af799bb45e448b 1、Dateset Dateset就是我们的目标数据&#xff0c;告诉我们如何获取数据&#xff0c;距离&#xff1a;从多种类型的数据中&#xff0c;提取…

Go语言反射入门:理解类型与值的动态操作

简介 Go 语言的反射机制是一种在运行时检查程序本身的能力&#xff0c;它允许程序在运行时动态地操作对象的类型和值。 基本概念 1.反射与类型 在静态类型语言中&#xff0c;变量的类型在编译时确定。反射允许在运行时查询和修改变量的类型信息。 2.接口与反射 Go 中的接口…

云等保安全合规解决方案

在当今数字化时代&#xff0c;云计算已成为企业数字化转型的基石&#xff0c;它不仅极大地提升了数据处理能力、降低了运营成本&#xff0c;还促进了业务模式的创新与发展。然而&#xff0c;随着云服务的广泛应用&#xff0c;云环境的安全性问题也日益凸显&#xff0c;成为制约…

Tita的OKR:研发人员的OKR

当您要建立一个以产品为中心的团队&#xff0c;并希望你的团队有一个产品的心态和时刻围绕你的客户&#xff0c;此工程研发 OKR 示例就是实现此目标的伟大方法。您将在以下文章中找到相关的技术研发 OKR 示例。 技术研发团队是任何组织中的重要组成部分&#xff0c;正确的OKR可…

U盘车载专用音乐合集 3068首 24G

包含3068首适合车载播放的音乐。 拿走的麻烦评论一下&#xff0c;感谢&#xff01;&#xff01;&#xff01; 拿走的麻烦评论一下&#xff0c;感谢&#xff01;&#xff01;&#xff01; 拿走的麻烦评论一下&#xff0c;感谢&#xff01;&#xff01;&#xff01; 链接&#…

主流短视频评论采集python爬虫(含一二级评论内容)

声明 仅用于学习交流&#xff0c;不用于其他用途 正文 随着主流短视频评论采集更新需要登录&#xff0c;由于不懈的努力&#xff0c;攻破这一难点&#xff0c;不需要登录采集作品所有评论信息 话不多说上代码看效果&#xff1a; 输入作品id: 这样就拿到评论信息了&#xff…

c++中调用函数时出现“warning C4715: “controlMode”: 不是所有的控件路径都返回值”警告的问题

调用函数时出现“warning C4715: “controlMode”: 不是所有的控件路径都返回值”警告的问题 问题描述解决方案 问题描述 如图所示&#xff0c;我的函数定义如下 在编译的时候&#xff0c;会出现如下警告 warning C4715: “controlMode”: 不是所有的控件路径都返回值 解决方案…

易通博客项目测试报告

目录 1. 项目背景1.1 测试目标 2. 项目功能3.测试分类3.1 功能测试3.2 自动化测试3.2.1自动化测试遇到的问题以及解决&#xff1a;3.2.2 自动化测试结果 3.3 性能测试 4. 基于场景性能测试下遇到的一些问题4.1 解决博客id不存在的问题&#xff1f;4.2 添加博客请求响应失败&…

[Other]-安装ruby、ascli、ascp

最近新接到这样一个需求&#xff0c;将生物原始数据上传到某中心&#xff0c;其中用到ascp命令&#xff0c;阴差阳错的装了ruby、ascli&#xff0c;这里就都一并介绍下安装方式&#xff0c;由于服务器老旧默认安装时ruby2.0&#xff0c;又 升级到2.7等引发的一系列问题&#xf…

Anaconda与conda、pip与conda的区别

Anaconda与conda、pip与conda的区别 1. 引言1.1 背景介绍1.2 文章目的 2. 什么是Anaconda&#xff1f;2.1 Anaconda简介2.2 Anaconda的优势2.3 Anaconda的安装与配置 3. 什么是Conda&#xff1f;3.1 Conda简介3.2 Conda的功能和用途3.3 Conda与Anaconda的关系 4. 什么是Pip&…

如何将精益生产目标的设定与企业财务状况相结合?

在探讨如何将精益生产目标的设定与企业财务状况相结合时&#xff0c;我们首先需要明确两者的核心要素及其相互关系。精益生产&#xff0c;起源于丰田生产方式&#xff0c;旨在通过消除浪 费、持续改进和全员参与&#xff0c;实现生产过程的最大化效率和最小化成本。而企业财务状…

NC 寻找第K大

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 有一个整数数…

Prometheus 和 Grafana 通过nginx-exporter监控nginx

在生产环境下&#xff0c;您已经部署了 Prometheus 和 Grafana&#xff0c;并希望通过它们来监控另一台 Ubuntu 20.04 上的 Nginx 服务。以下是配置步骤&#xff1a; 1. 安装和配置 nginx-exporter (Nginx 的 Prometheus 导出器) nginx-exporter 是 Prometheus 用来从 Nginx …

Godot《躲避小兵》实战之创建敌人

是时候创建一些玩家必须躲避的敌人了。它的行为很简单&#xff1a;怪物将随机生成在屏幕的边缘&#xff0c;沿着随机的方向直线移动。 我们将创建一个 Mob 的怪物场景&#xff0c;以便在游戏中独立实例化出任意数量的怪物。 节点设置 点击顶部菜单的“场景 -> 新建场景”…

C++初学(14)

14.1、while循环 和for循环相比&#xff0c;while循环没有初始化和更新部分&#xff0c;它只有测试条件和循环体。 while(text-condition)body首先程序计算圆括号内的测试条件&#xff08;text-condition&#xff09;表达式。如果该表达式为ture&#xff0c;则执行循环体中的…

短剧系统搭建:从零搭建高效创意内容平台教程,源码分享+正版片源授权指南

目录 一、短剧系统是什么&#xff1f; 二、短剧系统怎么搭建 技术选型 安全与性能优化 测试与部署 运营与维护 三、部分代码展示 一、短剧系统是什么&#xff1f; 短剧是一种采用单集时长15—30分钟的系列剧、集数在6集内的系列单元剧、20集内的连续剧、周播剧等多种形态…