EntityListeners @Transactional of Demoiselle - Id null

1

I'm setting up auditing on a project with JSF + Hibernate + Demoiselle .

Class Item:

@Entity
@Cacheable(true)
@Table(name = "itens")
@EntityListeners(value = PersistenceAuditor.class)
@XmlRootElement
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Item {
   private static final long serialVersionUID = 1L;
   @Id
   GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "id")
   private Long id;
   @LazyCollection(LazyCollectionOption.FALSE)
   @OneToMany(mappedBy = "item", orphanRemoval = true, cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
   @JsonManagedReference(value="itemParam")
   private List<ItemParam> params;

ItemParam Class:

@Entity
@Cacheable(true)
@Table(name = "item_params")
@EntityListeners(value = PersistenceAuditor.class)
@XmlRootElement
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class ItemParam {
   private static final long serialVersionUID = 1L;
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Column(name = "id")
   private Long id;
   @NotNull
   @ManyToOne
   @JoinColumn(name = "item_id", referencedColumnName = "id", nullable = false)
   @JsonBackReference(value="itemParam")
   private Item item;

No PersistenceAuditor:

@PostPersist
public void postPersist(Object object) {
... consome auditoria

And to save:

@Transactional    
public String insert() {
   this.itemBC.insert(this.getBean());
   return getPreviousView();
}

ItemBC

@BusinessController
public class ItemBC extends DelegateCrudExt<Item, Long, ItemDAO> {

Audit is persistent however with objects with id null as if it took the object before it was "comitative" and I would like the object already updated. Maybe because of the @Transactional.

Object output:

Item{"id":69,"params":[{"id":null,"valor":10.0"}]}
ItemParam{"id":3,"valor":10.0}

Where should be something like:

Item{"id":69,"params":[{"id": 3,"valor":10.0"}]}
ItemParam{"id":3, "item":69, "valor":10.0}

Any ideas to solve this?

    
asked by anonymous 23.06.2016 / 16:18

1 answer

1

According to the Java Persistence API (Version 2.1) specification on page 101:

  

It is implementation-dependent to whether callback methods are   invoked before or after the cascading of the lifecycle events to   related entities. Applications should not depend on this ordering.

Basically this means that the item's postPersist method can be called before the itemParam is persisted.

If the methods are executed in this order, the desired behavior would be obtained:

  • persist Item
  • persist ItemParam
  • Item postPersist
  • ItemParam postPersist

But execution can also happen in this order:

  • persist Item
  • Item postPersist
  • persist ItemParam
  • ItemParam postPersist

If they run in this order, you notice that the itemParam will have null id in the ItemPersist, since the itemParam persist has not yet been called.

According to the jpa specification the implementer (hibernate) can execute the methods on either of the two orders, so your code has to be made to work regardless of the order that hibernate has chosen.

I think it's best not to use postPersist in this case. A solution would be to do a function in the ItemDAO that calls the persist in the Item (which will give persist in the cascaded params) and then consumes the audit (and everything will already be with correct id since the persist of the params already generated the ids).

    
24.06.2016 / 15:11