使用 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。 nodeId
和 timelineId
不是空值。如果我在最后一行使用调试器,在 prePersist
之外,我会看到 hoTimelineType
具有我之前设置的值。
当我加载实体并插入测试数据时,一切正常,hoTimelineType
和 hoTimelineTypeValue
都没有可为 null 的值。
我跳过了TimelineKey
和HoTimelineType
的代码以简化示例。如果需要,可以添加它。
什么可以重置 hoTimelineType
?我想念什么?
似乎无法控制 spring jpa 存储库代理的保存行为。
问题的可能解决方案:
- 通过
javax.persistence.Converter
。很明显,实体的结构很简单。可以确认它与 Spring Jpa 存储库生成一起正常工作。
- 在保存实体之前明确设置
hoTimelineTypeValue
。 Error-prone 解决方案。每次保存实体时,您都必须考虑 hoTimelineTypeValue
和 hoTimelineType
. 之间的区别
- 您可以丰富实体 class 的 setter 和 getter,以明确控制字段之间的一致性。它使实体 classes 的实现不那么明显。您可以免费获得更复杂的解决方案。结果error-prone解决。也不推荐。
#2 和#3 的缺点原因我不提供示例。没有意义。
可以在此处找到解决方案 #1 的示例:Using JPA 2.1 @Converter Annotation
我有一个 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。 nodeId
和 timelineId
不是空值。如果我在最后一行使用调试器,在 prePersist
之外,我会看到 hoTimelineType
具有我之前设置的值。
当我加载实体并插入测试数据时,一切正常,hoTimelineType
和 hoTimelineTypeValue
都没有可为 null 的值。
我跳过了TimelineKey
和HoTimelineType
的代码以简化示例。如果需要,可以添加它。
什么可以重置 hoTimelineType
?我想念什么?
似乎无法控制 spring jpa 存储库代理的保存行为。
问题的可能解决方案:
- 通过
javax.persistence.Converter
。很明显,实体的结构很简单。可以确认它与 Spring Jpa 存储库生成一起正常工作。 - 在保存实体之前明确设置
hoTimelineTypeValue
。 Error-prone 解决方案。每次保存实体时,您都必须考虑hoTimelineTypeValue
和hoTimelineType
. 之间的区别
- 您可以丰富实体 class 的 setter 和 getter,以明确控制字段之间的一致性。它使实体 classes 的实现不那么明显。您可以免费获得更复杂的解决方案。结果error-prone解决。也不推荐。
#2 和#3 的缺点原因我不提供示例。没有意义。
可以在此处找到解决方案 #1 的示例:Using JPA 2.1 @Converter Annotation