学习
实践
活动
工具
TVP
写文章
专栏首页MyJavaJPA出现的数据库枚举映射的问题以及一步步优化

JPA出现的数据库枚举映射的问题以及一步步优化

问题

环境:一个枚举(name,id),数据库只存枚举的id。

当我们从数据库取出这个id对应的整条记录时,JPA会帮助我们对枚举自动映射(id到对应的枚举)。

今天这个地方出错了,id总是映射到错误的枚举上。

解决

1,仅传递枚举名,这样不需要映射。但是对未来修改和扩展有非常非常大的问题。

2,编写工具类xxxEnumUtils。

逻辑:我们可以每次调用工具类,然后手动映射传回去。

操作:遍历枚举的value,对比每个id,相同则返回这个枚举。

缺点:同时多个枚举不能共用同一个,实现在下面。

3,现在的解决方法

大部分情况下,我们需要检查@Enumerated()内的东西。

JPA提供给我们两种枚举映射的方法。

EnumType.Ordinal:

按照顺序,数据库存的是枚举的id。

这玩意有个缺点,一定是按顺序的,我们没办法定义。

所以队友可能会在枚举中间加了个新枚举,导致整体id序列化错误(多一位)。

EnumType.Spring:

存的是枚举的名字,和第一种解决方法一样,我们没办法维护他,就是不能改枚举名。

所以这两种自带的枚举都有非常多的问题,这样我们的解决方法就出现了。

自定义一个枚举转换器,来实现自动转换。

这里我们就可以找到实体转换器,进行自定义转换。

public class EnumConvert implements AttributeConverter<StatusEnum, Integer> {
    @Override
    public Integer convertToDatabaseColumn(StatusEnum attribute) {
        return attribute.getValue();
    }

    @Override
    public StatusEnum convertToEntityAttribute(Integer dbData) {
        return StatusEnum.fromValue(dbData);
    }
}

但是我们肯定不能因为每个枚举都写一个转换器吧。

所以我们需要实现一种公有的转换器。

这时候就利用泛型。

我们肯定要先写一个接口。

public interface IBaseDbEnum {
    /**
     * 用于显示的枚举名
     *
     * @return
     */
    String getDisplay();

    /**
     * 存储到数据库的枚举值
     *
     * @return
     */
    Integer getValue();

    //按枚举的value获取枚举实例
    static <T extends IBaseDbEnum> T fromValue(Class<T> enumType, Integer value) {
        for (T object : enumType.getEnumConstants()) {
            if (Objects.equals(value, object.getValue())) {
                return object;
            }
        }
        throw new IllegalArgumentException("No enum value " + value + " of " + enumType.getCanonicalName());
    }
}

然后按照原来的方式,利用泛型实现

public class EnumConvert<T extends IBaseDbEnum> implements AttributeConverter<T, Integer> {
    @Override
    public Integer convertToDatabaseColumn(T attribute) {
        return attribute.getValue();
    }

    @Override
    public T convertToEntityAttribute(Integer dbData) {
        //先随便写,测试一下
        return (T) StatusEnum.Active;
    }
}

这样就解决问题了。

实体转换器:实现很简单,只需要实现两个接口就好。

关于项目优化的过程

最开始出现映射失误,以为没有加@Enumerated注解(实际原因不是,因为发现默认就是ordinal)。

考虑到后续spring扩展性很垃圾,所以采用ordinal了。

但是发现还是出错,排查后发现是因为ordinal是不看id的,只看顺序,原来定义枚举时从1开始,导致每次都错位。

所以在枚举类中加入了自定义的实体转换器。

后来第二个枚举又出现问题了,决定写个共用的自定义实体转换器,调用即可。

使用:子枚举直接继承这个父类的实体转换器方法就行。

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!
本文分享自作者个人站点/博客:https://blog.syjhxy.ltd/复制
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?给你个选择SpringDataJPA的理由!

    本章节主要对Spring Data JPA的整体情况以及与其相关的一些概念进行一个简单的介绍。

    架构悟道
  • Spring Data开发手册|Java持久化API(JPA)需要了解到什么程度呢?

    JPA,Java Persistence API是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系...

    浅羽技术
  • springboot(五):spring data jpa的使用

    在上篇文章springboot(二):web综合开发中简单介绍了一下spring data jpa的基础性使用,这篇文章将更加全面的介绍spring data ...

    纯洁的微笑
  • Spring Boot(五):Spring Boot Jpa 的使用

    在上篇文章《Spring Boot(二):Web 综合开发》中简单介绍了一下 Spring Boot Jpa 的基础性使用,这篇文章将更加全面的介绍 Sprin...

    纯洁的微笑
  • MyBatis的发展和选型

    相应的工具类如:springjdbc、jdbcutils、Apache DbUtils等。这样的工具类主要解决了一下几个问题:

    Java_老男孩
  • SpringBoot(五) :spring data jpa 的使用

    使用spring data jpa 开发时,发现国内对spring boot jpa全面介绍的文章比较少案例也比较零碎,因此写文章总结一下。

    前朝楚水
  • 一站式解决使用枚举的各种痛点

    但是在业务代码中,我们不希望依赖 ordinary() 进行业务运算,而是自定义数字属性,避免枚举值的增减调序造成影响。

    Coder小黑
  • SpringDateJPA 系列之 JPA 中的相关操作

      Persistence 对象主要作用是用于获取 EntityManagerFactory 对象的 。通过调用该类的 createEntityManagerF...

    Demo_Null
  • 第十三章:SpringBoot实战SpringDataJPA构建项目总结

    恒宇少年
  • Spring Boot从零入门8_mybatis + druid + mysql + workbench + docker 入门

    这篇文章主要学习关系型数据库主流的技术栈,我们使用 Docker 快速搭建一个 MySQL 数据库学习环境,通过 MySQL 官方提供的 Workbench 可...

    别打名名
  • 序列化与反序列化系列二:JPA 与 Querydsl

    其实JPA放在这里有些牵强,不过我们开始这个系列的研究是与JPA相关的,起源于数据库查询中自动生成的一段Dabatase相关代码。事实上,在简化orm代码时,序...

    程序员架构进阶
  • MyBatis 源码分析系列文章导读

    本篇文章是我为接下来的 MyBatis 源码分析系列文章写的一个导读文章。本篇文章从 MyBatis 是什么(what),为什么要使用(why),以及如何使用(...

    田小波
  • 应用对持久数据的管理 | 从开发角度看应用架构7

    当应用程序将数据存储在永久性存储中(例如flat file,XML文件或数据库的持久性数据)时,它被称为数据的持久性。 关系数据库是企业应用程序用来保存数据以供...

    魏新宇
  • ORM和 Spring Data Jpa

    什么是“持久化” 持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。

    chenchenchen
  • 浅谈JPA优缺点_sql优点

    一.JPA的理解 JPA的总体思想和现有hibernate、TopLink,JDO等ORM框架大体一致。总的来说,JPA包括以下3方面的技术:

    全栈程序员站长
  • SpringBoot详细研究-02数据访问

    Springboot对数据访问部分提供了非常强大的集成,支持mysql,oracle等传统数据库的同时,也支持Redis,MongoDB等非关系型数据库,极大的...

    用户1216676

扫码关注腾讯云开发者

领取腾讯云代金券