Springboot JPA 枚举Enum类型存入到数据库的操作

 更新时间:2021年01月29日 17:00:15   作者:miskss  
这篇文章主要介绍了Springboot JPA 枚举Enum类型存入到数据库的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

1、使用JPA 的@Enumerated 注解 ,可以直接将Enum映射到数据库中。

但是value的值只有两种方式选择,一种是使用枚举的序号映射,一种是枚举的名称来映射。

public enum EnumType {
 /** Persist enumerated type property or field as an integer. */
 ORDINAL,
 /** Persist enumerated type property or field as a string. */
 STRING
}

如果想存入枚举中的自定义的值,则需要实现AttributeConverter接口

2、实现AttributeConverter接口方式

/**
 * @param <DB> : 保存到数据库的数据类型
 * @author peter
 * date: 2019-05-15 16:57
 **/
public interface PersistEnum2DB<DB> {
 DB getData();
}
import javax.persistence.AttributeConverter;
/**
 * @param <ATTR> 实体类中枚举的类型,需实现{@link PersistEnum2DB} 接口
 * @param <DB> 保存到数据库的数据类型
 * @author peter
 * date: 2019-05-15 16:59
 */
public abstract class AbstractEnumConverter<ATTR extends Enum<ATTR> & PersistEnum2DB<DB>, DB> implements AttributeConverter<ATTR, DB> {
 private final Class<ATTR> clazz;
 public AbstractEnumConverter(Class<ATTR> clazz) {
 this.clazz = clazz;
 }
 @Override
 public DB convertToDatabaseColumn(ATTR attribute) {
 return attribute != null ? attribute.getData() : null;
 }
 @Override
 public ATTR convertToEntityAttribute(DB dbData) {
 if (dbData == null) return null;
 ATTR[] enums = clazz.getEnumConstants();
 for (ATTR e : enums) {
  if (e.getData().equals(dbData)) {
  return e;
  }
 }
 throw new UnsupportedOperationException("枚举转化异常。枚举【" + clazz.getSimpleName() + "】,数据库库中的值为:【" + dbData + "】");
 }
}

使用方式

import com.tourcoo.parking.enums.convert2db.AbstractEnumConverter;
import com.tourcoo.parking.enums.convert2db.PersistEnum2DB;
/**
 * @author peter
 * create: 2019-05-15 14:33
 **/
public enum PayStatus implements PersistEnum2DB<Integer> {
 NONPAY(0, "未支付"),
 PAID(1, "已支付");
 private int code;
 private String msg;
 PayStatus(int code, String msg) {
 this.code = code;
 this.msg = msg;
 }
 public int getCode() {
 return code;
 }
 public String getMsg() {
 return msg;
 }
 @Override
 public Integer getData() {
 return code;
 }
 public static class Converter extends AbstractEnumConverter<PayStatus, Integer> {
 public Converter() {
  super(PayStatus.class);
 }
 }
}
 //支付状态
 @Convert(converter = PayStatus.Converter.class)
 private PayStatus payStatus;

补充: SpringBoot | Jpa 将Java枚举映射为基本值类型

解决方法之一:

使用实体属性类型转换器AttributeConverter

场景假设:

在代码中使用枚举类来映射用户性别(如下代码所示),在数据库中使用字符映射性别(M ,F),Hibernate提供了AttributeConverter解决上述场景的转换问题

public enum Gender {
 
 MALE( 'M' ),
 FEMALE( 'F' );
 
 private final char code; 
 Gender(char code) {
 this.code = code;
 }
 
 public static Gender fromCode(char code) {
 if ( code == 'M' || code == 'm' ) {
  return MALE;
 }
 if ( code == 'F' || code == 'f' ) {
  return FEMALE;
 }
 throw new UnsupportedOperationException(
  "The code " + code + " is not supported!"
 );
 }
 
 public char getCode() {
 return code;
 }
}

User实体类定义如下,重点在 @Convert(converter = GenderConverter.class)注释

@Entity
@Data
@ToString
@Table(name = "user")
public class User {
 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Integer id;
 private String name;
 @Convert(converter = GenderConverter.class)
 private Gender gender;
}

定义一个GenderConverter的类,需要实现AttributeConverter接口,实现convertToDatabaseColumn和convertToEntityAttribute,作用是分别封装从实体类映射至数据库字段数值的逻辑和从数据库字段数值映射到代码实体类中的枚举类值。

public class GenderConverter implements AttributeConverter<Gender,Character> {
 
 @Override
 public Character convertToDatabaseColumn(Gender gender) {
 if ( gender == null ) {
  return null;
 } 
 return gender.getCode();
 }
 
 @Override
 public Gender convertToEntityAttribute(Character value) {
 if ( value == null ) {
  return null;
 } 
 return Gender.fromCode( value );
 }
}

测试

@SpringBootTest
@Slf4j
public class AttributeConverterTest {
 
 @Resource
 private UserRepository userRepository;
 
 @Test
 void should_user__when__give_user() {
 //given
 User user1 = new User(null,"Janny", Gender.FEMALE);
 User user2 = new User(null,"Tom", Gender.MALE);
 //when
 User actUser1 = userRepository.save(user1);
 User actUser2 = userRepository.save(user2);
 //then
 Assertions.assertNotNull(actUser1);
 Assertions.assertNotNull(actUser2);
 }
}

例外Hibernate也提供其他的方法,如使用@Enumerated注解,详情可阅读这篇文档

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。如有错误或未考虑完全的地方,望不吝赐教。

相关文章

  • SpringBoot Actuator埋点和监控及简单使用

    SpringBoot Actuator埋点和监控及简单使用

    最近做的项目涉及到埋点监控、报表、日志分析的相关知识,于是捣鼓的一番,下面把涉及的知识点及SpringBoot Actuator埋点和监控的简单用法,给大家分享下,感兴趣的朋友一起看看吧
    2021-11-11
  • 如何解决SpringBoot2.6及之后版本取消了循环依赖的支持问题

    如何解决SpringBoot2.6及之后版本取消了循环依赖的支持问题

    循环依赖指的是两个或者多个bean之间相互依赖,形成一个闭环,SpringBoot从2.6.0开始默认不允许出现Bean循环引用,解决方案包括在全局配置文件设置允许循环引用存在、在SpringApplicationBuilder添加设置允许循环引用、构造器注入
    2024-10-10
  • 基于jdk动态代理和cglib动态代理实现及区别说明

    基于jdk动态代理和cglib动态代理实现及区别说明

    这篇文章主要介绍了基于jdk动态代理和cglib动态代理实现及区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • SpringBoot配置文件、多环境配置、读取配置的4种实现方式

    SpringBoot配置文件、多环境配置、读取配置的4种实现方式

    SpringBoot支持多种配置文件位置和格式,其中application.properties和application.yml是默认加载的文件,配置文件可以根据环境通过spring.profiles.active属性进行区分,命令行参数具有最高优先级,可覆盖其他所有配置
    2024-09-09
  • 一文了解Java 线程池的正确使用姿势

    一文了解Java 线程池的正确使用姿势

    线程池在平时的工作中出场率非常高,基本大家多多少少都要了解过,可能不是很全面,本文和大家基于jdk8学习下线程池的全面使用,以及分享下使用过程中遇到的一些坑,希望对大家有所帮助
    2022-10-10
  • MyBatisPlus超详细分析条件查询

    MyBatisPlus超详细分析条件查询

    这篇文章主要介绍了MyBatisPlus条件查询的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • java中fork-join的原理解析

    java中fork-join的原理解析

    Fork/Join框架是Java7提供用于并行执行任务的框架,是一个把大任务分割成若干个小任务,今天通过本文给大家分享java中fork join原理,感兴趣的朋友一起看看吧
    2021-04-04
  • 有关于整体刷新和局部刷新frameset窗口

    有关于整体刷新和局部刷新frameset窗口

    本篇小编为大家介绍有关于整体刷新和局部刷新frameset窗口的方法,希望对有需要的朋友有所帮助。
    2013-04-04
  • Java死锁的产生原因及解决方法总结

    Java死锁的产生原因及解决方法总结

    Java中的死锁是指多个线程同时占用一些共享资源且彼此相互等待,从而导致所有的线程都被阻塞,不能继续执行程序的情况,本文小编给大家介绍了Java死锁的产生原因及解决方法总结,需要的朋友可以参考下
    2023-11-11
  • 自定义一个简单的JDBC连接池实现方法

    自定义一个简单的JDBC连接池实现方法

    下面小编就为大家分享一篇自定义一个简单的JDBC连接池实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12

最新评论