JPA EntityListeners
Latest posts by Prasad Kharkar (see all)
- PyCharm for Machine Learning - July 17, 2018
- Linear Discriminant Analysis using Python - April 30, 2018
- Principal Component Analysis using Python - April 30, 2018
In previous article, we learned how jpa lifecycle call methods are used to listen to events about entities, but these methods need to be implemented in entity class itself. What if we don’t want to include callback methods in entity classes? We can use jpa entitylisteners for this purpose.
JPA EntityListeners:
Jpa entitylisteners are not entities, they are simply java classes in which jpa lifecycle callback methods are implemented using annotations. Some points to note about jpa entitylisteners are:
- The listener class should have access to entity.
- Hence, method signature of callback method should have a single parameter that is compatible with the entity it listens to.
- JPA entitylisteners should have a public no arg constructor.
When attaching jpa entitylisteners to entities, these things are followed.
- Entities should defines entitylisteners using annotation @EntityListeners
- Multiple listeners can be listed.
- Whenever a lifecycle event occurs, provider iterates through the list of all jpa entitylisteners listed in @EntityListeners annotation and instantiates them in the order they are listed.
- Provider invokes callback methods of listener and passes entity instance to it.
- Callback methods from entity are invoked if there are any.
Let us see an example.
Employee table in database
Employee.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
package com.thejavageek.jpa.entities; import javax.persistence.Entity; import javax.persistence.EntityListeners; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.TableGenerator; import com.thejavageek.jpa.listeners.EmployeeLoggerListener; @Entity @EntityListeners(EmployeeLoggerListener.class) public class Employee { @TableGenerator(name = "employee_gen", pkColumnName = "gen_name", valueColumnName = "gen_val", allocationSize = 1, table = "id_gen") @Id @GeneratedValue(generator = "employee_gen", strategy = GenerationType.TABLE) private int idEmployee; private String firstName; private String lastName; private int salary; public int getIdEmployee() { return idEmployee; } public void setIdEmployee(int idEmployee) { this.idEmployee = idEmployee; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } } |
EmployeeLoggerListener.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
package com.thejavageek.jpa.listeners; import javax.persistence.PostPersist; import javax.persistence.PostRemove; import javax.persistence.PostUpdate; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; import com.thejavageek.jpa.entities.Employee; public class EmployeeLoggerListener { @PrePersist public void methodInvokedBeforePersist(Employee emp) { System.out.println("persisting employee with id = " + emp.getIdEmployee()); } @PostPersist public void methodInvokedAfterPersist(Employee emp) { System.out.println("Persisted employee with id = " + emp.getIdEmployee()); } @PreUpdate public void methodInvokedBeforeUpdate(Employee emp) { System.out.println("Updating employee with id = " + emp.getIdEmployee()); } @PostUpdate public void methodInvokedAfterUpdate(Employee emp) { System.out.println("Updated employee with id = " + emp.getIdEmployee()); } @PreRemove private void methodInvokedBeforeRemove(Employee emp) { System.out.println("Removing employee with id = " + emp.getIdEmployee()); } @PostRemove public void methodInvokedAfterRemove(Employee emp) { System.out.println("Removed employee with id = " + emp.getIdEmployee() ); } } |
Test this out using code below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Employee employee = new Employee(); employee.setFirstName("prasad"); employee.setLastName("kharkar"); employee.setSalary(100000); em.persist(employee); int idEmployee = employee.getIdEmployee(); transaction.commit(); transaction.begin(); employee = (Employee) em.find(Employee.class, idEmployee); employee.setSalary(employee.getSalary() + 10000); transaction.commit(); transaction.begin(); em.persist(employee); em.remove(employee); transaction.commit(); |
This persists the employee in database and prints out following.
persisting employee with id = 10
Persisted employee with id = 10
Updating employee with id = 10
Updated employee with id = 10
Removing employee with id = 10
Removed employee with id = 10
I hope this example helped understand jpa entitylisteners.
References for further study :
- Apress: Mastering Java Persistence API 2.o book.
- JPA Tutorial
- JPA javadoc
Is there any difference in implementation when using SessionFactory. I am using the same with HibernateUtil Configuration Class. It doesn’t Works. If you could , please help me.