JPA supports user defined entity lifecycle callback methods (listeners), where JPA runtime can send notifications during entities operations.
To define listeners, we can use following method level annotations:
@PrePersist //Fired when EntityManager.persist() is called but before DML Insert execution.
void onPrePersist() {}
@PostPersist //Fired after EntityManager.persist() - probably on commit() or flush() but might be before that
void onPostPersist() {}
@PostLoad //Fired whenever an entity is loaded via SQL Select statements. Note that there's no @PreLoad annotation
void onPostLoad() {}
@PreUpdate//Fired on any operation which is about to execute a DML Update statement for the entity.
void onPreUpdate() {}
@PostUpdate//Fired after any operation which has executed a DML Update statement for the entity.
void onPostUpdate() {}
@PreRemove//Fired when EntityManager.remove() is called but before DML Delete execution.
void onPreRemove() {}
@PostRemove//Fired after EntityManager.remove() - probably on commit or flush but might be before that
void onPostRemove() {}
The callback methods can have any names, they should not be static or final and their return type should always be void.
These methods can be defined in an entity class or in a dedicated listener class.
When these methods used in an entity class they should take no arguments.
When these methods used in a dedicated listener class, they take one argument. This one argument should be the entity type which we are interested in receiving notification for. This argument type can also be java.lang.Object in which case we will receive events for all entities instead of a specific one.
In following example, we will understand how to use these listener methods in an entity class.
Example
The Entity
@Entity
public class MyEntity {
@Id
@GeneratedValue
private int id;
private String msg;
public MyEntity() { }
public MyEntity(String msg) {
this.msg = msg;
}
@PrePersist
void onPrePersist() {
System.out.println("MyEntity.onPrePersist()");
}
@PostPersist
void onPostPersist() {
System.out.println("MyEntity.onPostPersist()");
}
@PostLoad
void onPostLoad() {
System.out.println("MyEntity.onPostLoad()");
}
@PreUpdate
void onPreUpdate() {
System.out.println("MyEntity.onPreUpdate()");
}
@PostUpdate
void onPostUpdate() {
System.out.println("MyEntity.onPostUpdate()");
}
@PreRemove
void onPreRemove() {
System.out.println("MyEntity.onPreRemove()");
}
@PostRemove
void onPostRemove() {
System.out.println("MyEntity.onPostRemove()");
}
.............
}
Preforming Entity Operations
Persisting Entity
System.out.println("-- persisting --");
MyEntity myEntity = new MyEntity("test msg");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
System.out.println("before EntityManager.persist()");
em.persist(myEntity);
System.out.println("after EntityManager.persist()");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
output
-- persisting --
before EntityManager.persist()
MyEntity.onPrePersist()
after EntityManager.persist()
before EntityManager.commit()
MyEntity.onPostPersist()
after EntityManager.commit()
Loading and Updating
System.out.println("-- loading and updating --");
EntityManager em = entityManagerFactory.createEntityManager();
System.out.println("before EntityManager.find()");
MyEntity myEntity = em.find(MyEntity.class, 1);
System.out.println("after EntityManager.find()");
em.getTransaction().begin();
System.out.println("before updating entity in transaction");
myEntity.setMsg("new test msg");
System.out.println("after updating entity in transaction");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
output
-- loading and updating --
before EntityManager.find()
MyEntity.onPostLoad()
after EntityManager.find()
before updating entity in transaction
after updating entity in transaction
before EntityManager.commit()
MyEntity.onPreUpdate()
MyEntity.onPostUpdate()
after EntityManager.commit()
Merging
System.out.println("-- merging --");
MyEntity myEntity = new MyEntity();
myEntity.setId(1);
myEntity.setMsg("New merged msg");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
System.out.println("before EntityManager.merge()");
em.merge(myEntity);
System.out.println("after EntityManager.merge()");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
output
-- merging --
before EntityManager.merge()
MyEntity.onPostLoad()
after EntityManager.merge()
before EntityManager.commit()
MyEntity.onPreUpdate()
MyEntity.onPostUpdate()
after EntityManager.commit()
Removing
System.out.println("-- loading and removing --");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
System.out.println("before EntityManager.find()");
MyEntity myEntity = em.find(MyEntity.class, 1);
System.out.println("after EntityManager.find()");
System.out.println("before EntityManager.remove()");
em.remove(myEntity);
System.out.println("after EntityManager.remove()");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
output
-- loading and removing --
before EntityManager.find()
MyEntity.onPostLoad()
after EntityManager.find()
before EntityManager.remove()
MyEntity.onPreRemove()
after EntityManager.remove()
before EntityManager.commit()
MyEntity.onPostRemove()
after EntityManager.commit()
Complete Example
public class ExampleMain {
private static EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("example-unit");
public static void main(String[] args) {
try {
persistEntity();
loadAndUpdateEntity();
mergeEntity();
loadAndRemoveEntity();
} finally {
entityManagerFactory.close();
}
}
public static void persistEntity() {
System.out.println("-- persisting --");
MyEntity myEntity = new MyEntity("test msg");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
System.out.println("before EntityManager.persist()");
em.persist(myEntity);
System.out.println("after EntityManager.persist()");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
}
public static void loadAndUpdateEntity() {
System.out.println("-- loading and updating --");
EntityManager em = entityManagerFactory.createEntityManager();
System.out.println("before EntityManager.find()");
MyEntity myEntity = em.find(MyEntity.class, 1);
System.out.println("after EntityManager.find()");
em.getTransaction().begin();
System.out.println("before updating entity in transaction");
myEntity.setMsg("new test msg");
System.out.println("after updating entity in transaction");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
}
public static void mergeEntity() {
System.out.println("-- merging --");
MyEntity myEntity = new MyEntity();
myEntity.setId(1);
myEntity.setMsg("New merged msg");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
System.out.println("before EntityManager.merge()");
em.merge(myEntity);
System.out.println("after EntityManager.merge()");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
}
public static void loadAndRemoveEntity() {
System.out.println("-- loading and removing --");
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
System.out.println("before EntityManager.find()");
MyEntity myEntity = em.find(MyEntity.class, 1);
System.out.println("after EntityManager.find()");
System.out.println("before EntityManager.remove()");
em.remove(myEntity);
System.out.println("after EntityManager.remove()");
System.out.println("before EntityManager.commit()");
em.getTransaction().commit();
System.out.println("after EntityManager.commit()");
em.close();
}
} -- persisting -- before EntityManager.persist() MyEntity.onPrePersist() after EntityManager.persist() before EntityManager.commit() MyEntity.onPostPersist() after EntityManager.commit() -- loading and updating -- before EntityManager.find() MyEntity.onPostLoad() after EntityManager.find() before updating entity in transaction after updating entity in transaction before EntityManager.commit() MyEntity.onPreUpdate() MyEntity.onPostUpdate() after EntityManager.commit() -- merging -- before EntityManager.merge() MyEntity.onPostLoad() after EntityManager.merge() before EntityManager.commit() MyEntity.onPreUpdate() MyEntity.onPostUpdate() after EntityManager.commit() -- loading and removing -- before EntityManager.find() MyEntity.onPostLoad() after EntityManager.find() before EntityManager.remove() MyEntity.onPreRemove() after EntityManager.remove() before EntityManager.commit() MyEntity.onPostRemove() after EntityManager.commit()
Example ProjectDependencies and Technologies Used: - h2 1.4.196: H2 Database Engine.
- hibernate-core 5.2.12.Final: The core O/RM functionality as provided by Hibernate.
Implements javax.persistence:javax.persistence-api version 2.1 - JDK 1.8
- Maven 3.3.9
|