如何使用Hibernate读取数组中存储为缩写的枚举集合
解决方案:映射PostgreSQL char(3)[]数组到Set
要解决Hibernate对数组存储的枚举缩写集合的双向转换问题,需要实现针对集合类型的AttributeConverter,并配合Hibernate的数组类型映射,具体步骤如下:
1. 实现集合转换器
创建AttributeConverter,负责Set<DayOfWeek>与数据库char(3)[]对应的String[]之间的双向转换:
import java.util.Arrays; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.persistence.AttributeConverter; import javax.persistence.Converter; import java.time.DayOfWeek; @Converter(autoApply = false) public class DayOfWeekSetConverter implements AttributeConverter<Set<DayOfWeek>, String[]> { // 枚举与数据库缩写的映射关系 private static final Map<DayOfWeek, String> DAY_TO_ABBR = Map.of( DayOfWeek.MONDAY, "mon", DayOfWeek.TUESDAY, "tue", DayOfWeek.WEDNESDAY, "wed", DayOfWeek.THURSDAY, "thu", DayOfWeek.FRIDAY, "fri", DayOfWeek.SATURDAY, "sat", DayOfWeek.SUNDAY, "sun" ); private static final Map<String, DayOfWeek> ABBR_TO_DAY = DAY_TO_ABBR.entrySet() .stream() .collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey)); @Override public String[] convertToDatabaseColumn(Set<DayOfWeek> days) { if (days == null || days.isEmpty()) { return null; } return days.stream() .map(DAY_TO_ABBR::get) .toArray(String[]::new); } @Override public Set<DayOfWeek> convertToEntityAttribute(String[] dbAbbrs) { if (dbAbbrs == null || dbAbbrs.length == 0) { return Collections.emptySet(); } return Arrays.stream(dbAbbrs) .map(ABBR_TO_DAY::get) .collect(Collectors.toSet()); } }
2. 配置实体类属性
在Schedule实体的daysOfWeek属性上,同时添加三个注解:
@Column:指定数据库列类型为char(3)[]@Type:指定Hibernate的数组类型处理器ArrayType@Convert:关联上面实现的集合转换器
import java.time.DayOfWeek; import java.util.Set; import javax.persistence.Column; import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.Type; @Entity @Table(name = "schedule") public class Schedule { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 其他属性... @Column(name = "days_of_week", columnDefinition = "char(3)[]") @Type(type = "org.hibernate.type.ArrayType") @Convert(converter = DayOfWeekSetConverter.class) private Set<DayOfWeek> daysOfWeek; // Getter、Setter方法... }
关键说明
- 为什么之前的方法失效?
- 直接映射:Hibernate无默认规则将数据库数组转换为枚举集合,抛出类型转换异常
@Enumerated(EnumType.STRING):枚举默认名称(如MONDAY)与数据库缩写(mon)不匹配,无法映射- 单个枚举转换器:仅支持单个
DayOfWeek与缩写的转换,无法直接作用于Set集合 @ElementCollection:用于将集合映射到关联表,而非数据库原生数组列,不符合需求
- 注意事项:确保数据库中存储的缩写与转换器中的映射完全一致(大小写、长度),避免转换失败
- 兼容性:Hibernate的
ArrayType支持PostgreSQL等原生数组类型的数据库,无需额外依赖
内容的提问来源于stack exchange,提问作者danissimo
相关产品推荐
相关产品推荐

