使用 Spring JPARepository 保存实体会重置枚举类型值

Saving entity with Spring JPA Repository resets enum ttype value

我有一个 TimelineEntity 实体,它使用具有自定义整数值的 HoTimelineType 枚举。该自定义整数值存储在数据库中。通过 Using @PostLoad and @PrePersist Annotations

实施

Sprint JPA Repository 用于保存和获取实体。

这是问题所在:

@Entity
@Table(name = TABLE_NAME)
@IdClass(TimelineKey.class)
public class TimelineEntity {

  public interface Persistence {
    String TABLE_NAME = "timelines";
  }

  @Id
  @Column(name = "node_id")
  private Long nodeId;

  @Id
  @Column(name = "timeline_id")
  private Long timelineId;

  @Column(name = "ho_timeline_type")
  private Integer hoTimelineTypeValue;

  @Transient
  private HoTimelineType hoTimelineType;

  public Long getNodeId() {
    return nodeId;
  }

  public void setNodeId(Long nodeId) {
    this.nodeId = nodeId;
  }

  public Long getTimelineId() {
    return timelineId;
  }

  public void setTimelineId(Long timelineId) {
    this.timelineId = timelineId;
  }

  public HoTimelineType getHoTimelineType() {
    return hoTimelineType;
  }

  public void setHoTimelineType(HoTimelineType hoTimelineType) {
    this.hoTimelineType = hoTimelineType;
  }

  public Integer getHoTimelineTypeValue() {
    return hoTimelineTypeValue;
  }

  public void setHoTimelineTypeValue(Integer hoTimelineTypeValue) {
    this.hoTimelineTypeValue = hoTimelineTypeValue;
  }

  @PostLoad
  private void postLoad() {
    this.hoTimelineType = HoTimelineType.of(hoTimelineTypeValue);
  }

  @PrePersist
  private void prePersist() {
    this.hoTimelineTypeValue = hoTimelineType.getValue();
  }
}

@Eager
public interface TimelineEntityRepository extends JpaRepository<TimelineEntity, TimelineKey> {

  List<TimelineEntity> findByNodeId(Long nodeId);
}

@Autowired
private TimelineEntityRepository timelineEntityRepository;
...
TimelineEntity newTE = new TimelineEntity();
newTE.setNodeId(10L);
newTE.setTimelineId(22L);
newTE.setHoTimelineType(HoTimelineType.TYPE_1);

newTE = timelineEntityRepository.save(newTE);

保存 newTE 实体时,将调用 prePersist,在此方法中,hoTimelineType 为 null,我得到 NPE。 nodeIdtimelineId 不是空值。如果我在最后一行使用调试器,在 prePersist 之外,我会看到 hoTimelineType 具有我之前设置的值。

当我加载实体并插入测试数据时,一切正常,hoTimelineTypehoTimelineTypeValue 都没有可为 null 的值。

我跳过了TimelineKeyHoTimelineType的代码以简化示例。如果需要,可以添加它。

什么可以重置 hoTimelineType?我想念什么?

似乎无法控制 spring jpa 存储库代理的保存行为。

问题的可能解决方案:

  1. 通过javax.persistence.Converter。很明显,实体的结构很简单。可以确认它与 Spring Jpa 存储库生成一起正常工作。
  2. 在保存实体之前明确设置 hoTimelineTypeValue。 Error-prone 解决方案。每次保存实体时,您都必须考虑 hoTimelineTypeValuehoTimelineType.
  3. 之间的区别
  4. 您可以丰富实体 class 的 setter 和 getter,以明确控制字段之间的一致性。它使实体 classes 的实现不那么明显。您可以免费获得更复杂的解决方案。结果error-prone解决。也不推荐。

#2 和#3 的缺点原因我不提供示例。没有意义。

可以在此处找到解决方案 #1 的示例:Using JPA 2.1 @Converter Annotation