How to get entity manager or transaction in jpa listener

I used a Hibernate event listener, such as PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener , to perform some operations during insert, delete and update. Now I would like to use a JPA listener for this, because if I like to switch from Hibernate to any other JPA provider, my listener should work. The Hibernate listener gives me an event from which I can get the transaction and check if it was committed or rolled back. JPA listeners provide me with an entity object. Now, how can I get a transaction or session or noun. Entities in a JPA listener? Thanks in advance!! I use Jboss as my CMT.

+6
source share
3 answers

This is not supported by JPA 2.0.

In JPA 2.1 (assumed to be in Java EE 7), the persistence provider will treat entity listeners as CDI beans when in a managed environment (such as a JBoss application server). From Proposed Final Specification for JPA 2.1 , p. 96:

Entity listener classes in Java EE environments support injection dependency through the context and dependency injection (CDI) API [10] when the containing archive is a bean. An entity listener class that uses CDI injection can also define lifecycle callback methods annotated using PostConstruct and PreDestroy annotations. These methods will be called after the injection place and until the instance of the listener is destroyed, respectively

So, in JPA 2.1, if you create a CDI producer that provides the EntityManager (just annotating the @PersistenceContext field with @Produces), you can simply insert the EntityManager into the listener.

At the same time, I do not know a single clean or pleasant workaround. The β€œworst” I can think of is setting up the EntityManager to bind in JNDI, and then retrieve it through a JNDI search from inside the listener.

+6
source

In my case, I use this code:

 ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext(); auditLogService = (AuditLogService) ctx.getBean("auditLogService"); 

This works well for me.

The code for this application can be downloaded at https://bitbucket.org/macielbombonato/apolo

I hope this can help you.

+1
source

You can use all listening before / after loading, pasting, updating or deleting in JPA in two ways:

  • Using annotation. A simple example of using a Listener is where the object has a transition variable that must be filled after the object has been saved, updated, or loaded, for example:

     public class AvailableCreditListener { @PostLoad @PostPersist @PostUpdate public void calculateAvailableCredit(Account account) { account.setAvailableCredit( account.getBalance().add( account.getOverdraftLimit())); } } 

    An entity class will be annotated using @EntityListeners:

     @EntityListeners({AvailableCreditListener.class}) public class Account extends BaseEntity { private BigDecimal balance; private BigDecimal overdraftLimit; @Transient private BigDecimal availableCredit; // getters and setters } 
  • Using the persistence.xml configuration file.

Finally, instead of annotations, the XMl mapping file can be used and deployed with the application to specify default listeners. (This mapping file refers to the persistence.xml file.) But an entity can use the @ExcludeDefaultListeners annotation if it does not want to use default listeners.

 @ExcludeDefaultListeners @Entity public class Account extends BaseEntity { .... } 

In your persistence.xml:

 <persistence-unit-metadata> <persistence-unit-defaults> <entity-listeners> <entity-listener class="samples.AvailableCreditListener"/> </entity-listeners> </persistence-unit-defaults> </persistence-unit-metadata> 
-1
source

Source: https://habr.com/ru/post/928014/


All Articles