How to invoke callback methods like @PreUpdate, @PrePersist, @PreRemove while doing bulk update, delete, insert in JPA 2.1?
-
20-12-2019 - |
Domanda
How to call a method annotated by @PreUpdate
(including @PrePersist
, @PreRemove
and others) in JPA 2.1? Given the following CriteriaUpdate
query as an example:
Brand brand=//... Populated by client. The client is JSF in this case.
byte[] bytes=//... Populated by client. The client is JSF in this case.
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaUpdate<Brand>criteriaUpdate=criteriaBuilder.createCriteriaUpdate(Brand.class);
Root<Brand> root = criteriaUpdate.from(entityManager.getMetamodel().entity(Brand.class));
criteriaUpdate.set(root.get(Brand_.brandName), brand.getBrandName());
criteriaUpdate.set(root.get(Brand_.category), brand.getCategory());
criteriaUpdate.set(root.get(Brand_.brandImage), bytes);
criteriaUpdate.where(criteriaBuilder.equal(root, brand));
entityManager.createQuery(criteriaUpdate).executeUpdate();
Given the method decorated by @PreUpdate
in the associated entity - Brand
.
@Column(name = "last_modified")
@Temporal(TemporalType.TIMESTAMP)
private Date lastModified; //Getter and setter.
@PreUpdate
public void onUpdate() {
lastModified = new Date();
System.out.println("lastModified = "+lastModified);
}
This method is only invoked, when a row is updated using
entityManager.merge(brand);
How to invoke a method decorated by @PreUpdate
(or @PrePersist
, @PreRemove
), when relevant operations involve the criteria API like CriteraUpdate
?
Soluzione
You're not passing the entity to JPA. You're merely extracting the individual entity properties and passing them to JPA. In order to get the entity's @PreUpdate
and friends invoked by JPA, you need to pass the whole entity to JPA, like as usual with EntityManager#merge()
.
If that's not an option for some unclear reason (perhaps the entity is way too large and you'd like to skip unnecessary properties from being updated? in such case, consider splitting the entity over smaller @OneToOne
relationships), then you'd need to manually invoke those methods on the entity before extracting and passing the entity's properties to JPA.
Brand brand = ...
brand.onUpdate();
byte[] bytes = ...
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
// ...