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

时间:2021-05-20

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@Slf4jpublic 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注解,详情可阅读这篇文档

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

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章