0

A failed save attempt (EntityManager persist) leaves my entity with an id.

In my case, I'm returning to the view with any ConstraintViolationException thrown as error messages along with the original entity. The view checks to see if the entity has an id to include in the form action url used when submitting an event. The controller then attempts to load the entity by id.

When this code is run within my Spring MVC action method on a new unsaved event:

eventRepository.save(event);

and throws an exception (caused by ConstraintViolationException) the event entity which is in Spring's org.springframework.ui.Model now contains an id! Why?

The EventRepository used exetends from Spring Data JPA's JpaRepository:

public interface EventRepository extends JpaRepository<Event, Long> {}

Here's a snippet of the Event entity bean:

@Entity
public class Event {

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "EVENT_SEQ")
  @SequenceGenerator(name = "EVENT_SEQ", sequenceName = "ID_SEQ", allocationSize = 1)
  private Long id;

  @NotNull(message = "{event.proctor.null}")
  @ManyToOne
  @JoinColumn(name="PROCTOR_EMPLOYEE_ID")
  private Employee proctor;

  @NotNull(message = "{event.date.time.null}")
  @Column(name="EVENT_DATE_TIME")
  @Convert(converter = LocalDateTimePersistenceConverter.class)
  @DateTimeFormat(pattern = "yyyy-MM-dd HHmm")
  private LocalDateTime eventDateTime;
...
Brice Roncace
  • 10,110
  • 9
  • 60
  • 69

1 Answers1

0

You can find the behaviour on transaction rollback in the JPA specification described here. Imagine, that you do two operations in the same transaction:

//begin transaction
em.persist(entity1);
em.merge(entity2);//here is thrown an exception
//commit transaction

In this example it is JPA-compliant, that you get an ID in entity1, because on transaction rollback, namely when the merge() is called, entity1 has an ID. Please also note that the PersistentContext may remain in an unconsistent state according to JPA. Also please check the diffference between perist() and merge() (persist does not return anything, as the entity1 will get managed after that call).

Community
  • 1
  • 1
V G
  • 18,822
  • 6
  • 51
  • 89
  • This makes sense, thanks. In my case, however, I was expecting the bean validation to hook into the JPA2 life cycle during pre-persist (for persist) or pre-update (for merge) so that the entity would not have an id set on persist, but evidently this is not exactly how it works. – Brice Roncace Mar 19 '15 at 14:12
  • If you have validators, then you should check why they are not executed/why they do not do their job. But your original question about assigning an ID got an explanation. – V G Mar 20 '15 at 09:18