java 如何在 jpa 侦听器中获取实体管理器或事务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12951701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get entity manager or transaction in jpa listener
提问by Muzy
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.
我正在使用 Hibernate 事件侦听器,比如PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener
在插入、删除和更新期间做一些操作。现在我想使用 JPA 侦听器来执行此操作,因为如果我想从 Hibernate 移动到任何其他 JPA 提供程序,我的侦听器应该可以工作。Hibernate 侦听器为我提供了event
从中获取事务并检查其是否已提交或回滚的信息。JPA 侦听器仅向我提供实体对象。现在如何在 JPA 侦听器中获取事务或会话或实体管理器?提前致谢!!我使用 Jboss 作为我的 CMT。
采纳答案by Jonathan Fuerth
This is not supported as of JPA 2.0.
从 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:
在 JPA 2.1(计划在 Java EE 7 中)中,持久性提供程序将在托管环境(例如 JBoss 应用服务器)中将实体侦听器视为 CDI bean。来自JPA 2.1 规范的最终草案,第 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
当包含存档是 bean 存档时,Java EE 环境中的实体侦听器类支持通过上下文和依赖注入 API (CDI) [10] 进行依赖注入。使用 CDI 注入的实体侦听器类还可以定义使用 PostConstruct 和 PreDestroy 注释注释的生命周期回调方法。这些方法将分别在注入发生后和实体侦听器实例被销毁之前调用
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.
因此,在 JPA 2.1 中,如果您创建一个提供 EntityManager 的 CDI 生产者(只需使用 @Produces 注释 @PersistenceContext 字段),您只需将 EntityManager 注入监听器即可。
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.
与此同时,我不知道有任何干净或愉快的解决方法。我能想到的“最糟糕”的事情是将 EntityManager 配置为绑定在 JNDI 中,然后通过从侦听器中的 JNDI 查找获取它。
回答by Maciel Bombonato
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
此应用程序的代码可在https://bitbucket.org/macielbombonato/apolo下载
I hope that this can help you.
我希望这可以帮助你。
回答by Rahul Sharma
You can use all pre/post load, insert, update or delete listener in JPA by using two ways:
您可以通过以下两种方式在 JPA 中使用所有 pre/post 加载、插入、更新或删除侦听器:
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.
通过使用注释。使用侦听器的一个简单示例可能是实体具有一个瞬态变量,该变量需要在实体被持久化、更新或加载后填充,例如:
public class AvailableCreditListener { @PostLoad @PostPersist @PostUpdate public void calculateAvailableCredit(Account account) { account.setAvailableCredit( account.getBalance().add( account.getOverdraftLimit())); } }
实体类将使用@EntityListeners 进行注释:
@EntityListeners({AvailableCreditListener.class}) public class Account extends BaseEntity { private BigDecimal balance; private BigDecimal overdraftLimit; @Transient private BigDecimal availableCredit; // getters and setters }
通过使用persistence.xml 配置文件。
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.
最后,代替注释,可以使用 XMl 映射文件并将其与应用程序一起部署以指定默认侦听器。(该映射文件由persistence.xml 文件引用。)但如果实体不想使用默认侦听器,则可以使用@ExcludeDefaultListeners 批注。
@ExcludeDefaultListeners
@Entity
public class Account extends BaseEntity {
....
}
In your persistence.xml:
在您的persistence.xml 中:
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="samples.AvailableCreditListener"/>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>