I was using Hibernate event listener like PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener
to do some operations during insert, delete and update. Now I would like to use JPA listener to do this because if I like to move from Hibernate to any other JPA provider my listener should work. Hibernate listener gives me event
from which I can get the transaction and check whether its committed or rollback. JPA listeners only provides me the entity object. Now how can I get the transaction or session or entity manger in the JPA listener?? Thanks in advance!! I am using Jboss as my CMT.
This is not supported as of JPA 2.0.
In JPA 2.1 (slated to be in Java EE 7), the persistence provider will treat entity listeners as CDI beans when in a managed environment (such as the JBoss app server). From the Proposed Final Draft of the JPA 2.1 spec, page 96:
Entity listener classes in Java EE environments support dependency injection through the Contexts and Dependency Injection API (CDI) [ 10 ] when the containing archive is a bean archive. An entity listener class that makes use of CDI injection may also define lifecycle callback methods annotated with the PostConstruct and PreDestroy annotations. These methods will be invoked after injection has taken place and before the entity listener instance is destroyed respectively
So in JPA 2.1, if you create a CDI producer that provides EntityManager (simply by annotating a @PersistenceContext field with @Produces), you can just @Inject the EntityManager into the listener.
In the mean time, I'm not aware of any clean or pleasant workaround. The "least worst" thing I can think of would be to configure the EntityManager to be bound in JNDI, then obtain it through a JNDI lookup from within the listener.
In my case I'm using this code:
ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext();
auditLogService = (AuditLogService) ctx.getBean("auditLogService");
This works well to me.
The code of this application is available to download at https://bitbucket.org/macielbombonato/apolo
I hope that this can help you.
You can use all pre/post load, insert, update or delete listener in JPA by using two ways:
By using annotation. An simple example of using a Listener could be where an entity has a transient variable that needs to be populated after the entity has been persisted, updated or loaded, like:
public class AvailableCreditListener { @PostLoad @PostPersist @PostUpdate public void calculateAvailableCredit(Account account) { account.setAvailableCredit( account.getBalance().add( account.getOverdraftLimit())); } }
The entity class would be annotated with @EntityListeners:
@EntityListeners({AvailableCreditListener.class}) public class Account extends BaseEntity { private BigDecimal balance; private BigDecimal overdraftLimit; @Transient private BigDecimal availableCredit; // getters and setters }
By using persistence.xml configuration file.
Finally, instead of annotations, an XMl mapping file can be used and deployed with the application to specify default listeners. (This mapping file is referenced by the persistence.xml file.) But an entity can use the @ExcludeDefaultListeners annotation if it does not want to use the 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>
© 2022 - 2024 — McMap. All rights reserved.