Home > Software design >  Saving entity with Spring JPA Repository resets enum ttype value
Saving entity with Spring JPA Repository resets enum ttype value

Time:05-18

I have an TimelineEntity entity, that uses HoTimelineType enum with custom integer value. That custom integer value is stored in the database. Implemented via Using @PostLoad and @PrePersist Annotations

Sprint JPA Repository is used to save and get entities.

Here is the issue:

@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);

When the newTE entity is saved, prePersist is invoked, and inside this method, the hoTimelineType is null and I get NPE. nodeId and timelineId are not nulls. If I stay with a debugger on the last line, outside of prePersist, I see that hoTimelineType has the value, I set before.

When I load entities, inserted with test data, everything works fine and both hoTimelineType and hoTimelineTypeValue have not nullable values.

I skipped the code of TimelineKey and HoTimelineType to simplify the example. Can add it, if needed.

What could reset hoTimelineType? What do I miss?

CodePudding user response:

It seems there is no way to control the saving behaviour of spring jpa repository proxy.

Possible solutions for issue:

  1. Via javax.persistence.Converter. It is pretty clear, the structe of an entity is simple. Can confirm it works fine with Spring Jpa Repository generation.
  2. Explicitely set hoTimelineTypeValue before you save an entity. Error-prone solution. Everytime you save an entity you must think about the difference between the hoTimelineTypeValue and hoTimelineType.
  3. You could enrich setters and getters of the entity class, to explicitely control the consistency between the fields. It makes implementation of entity classes not so obvious. You get more compicated solution for nothing. As a result error-prone solution. Do not recommend it as well.

Cause of disadvantages of #2 and #3 I do not provide examples. It makes no sense.

Example of the solution #1 can be found here: Using JPA 2.1 @Converter Annotation

  • Related