Close

JPA - Understanding Entity Lifecycle Callback Methods

[Updated: Jan 10, 2018, Created: Jan 9, 2018]

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 Project

Dependencies 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

Entity Lifecycle Listeners Example Select All Download
  • jpa-entity-class-lifecycle-callback
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyEntity.java
          • resources
            • META-INF

    See Also