【问题标题】:How to get entity manager or transaction in jpa listener如何在 jpa 监听器中获取实体管理器或事务
【发布时间】:2012-10-08 17:41:23
【问题描述】:

我使用像PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener 这样的Hibernate 事件监听器在插入、删除和更新期间执行一些操作。现在我想使用 JPA 侦听器来执行此操作,因为如果我想从 Hibernate 移动到任何其他 JPA 提供程序,我的侦听器应该可以工作。 Hibernate 监听器给了我event,我可以从中获取事务并检查它是提交还是回滚。 JPA 侦听器只为我提供实体对象。现在如何在 JPA 侦听器中获取事务或会话或实体管理器?提前致谢!!我使用 Jboss 作为我的 CMT。

【问题讨论】:

    标签: java hibernate jpa jpa-2.0 jboss7.x


    【解决方案1】:

    您可以通过两种方式在 JPA 中使用所有预/后加载、插入、更新或删除侦听器:

    1. 通过使用注释。 使用侦听器的一个简单示例可能是实体有一个瞬态变量,该变量需要在实体被持久化、更新或加载后填充,例如:

      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
      }
      
    2. 通过使用persistence.xml配置文件。

    最后,可以使用 XML 映射文件代替注释,并将其与应用程序一起部署以指定默认侦听器。 (这个映射文件被persistence.xml文件引用。)但是如果一个实体不想使用默认监听器,它可以使用@ExcludeDefaultListeners注解。

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

    在您的 persistence.xml 中:

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

    【讨论】:

    • 我的问题是如何在 AvailableCreditListener 类中获取 entityManager
    • 我有同样的问题
    【解决方案2】:

    从 JPA 2.0 开始不支持此功能。

    在 JPA 2.1(预定在 Java EE 7 中)中,持久性提供程序在托管环境(例如 JBoss 应用服务器)中将实体侦听器视为 CDI bean。来自Proposed Final Draft of the JPA 2.1 spec,第 96 页:

    Java EE 环境中的实体监听器类支持依赖 通过上下文和依赖注入 API (CDI) [10] 进行注入 当包含档案是 bean 档案时。实体监听器 使用 CDI 注入的类也可以定义生命周期 使用 PostConstruct 和 PreDestroy 注释的回调方法 注释。这些方法将在注入完成后调用 在实体侦听器实例被销毁之前放置 分别

    所以在 JPA 2.1 中,如果您创建一个提供 EntityManager 的 CDI 生产者(只需使用 @Produces 注释 @PersistenceContext 字段),您只需将 EntityManager @Inject 注入到侦听器中。

    与此同时,我不知道有任何干净或令人愉快的解决方法。我能想到的“最糟糕”的事情是将 EntityManager 配置为绑定在 JNDI 中,然后通过 JNDI 查找从侦听器中获取它。

    【讨论】:

      【解决方案3】:

      就我而言,我正在使用此代码:

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

      这对我很有效。

      此应用程序的代码可在https://bitbucket.org/macielbombonato/apolo下载

      希望对你有帮助。

      【讨论】:

      • 这应该被记录为“一个答案”,但明确的答案(对于一般情况)将是,通过 JNDI 查找获取 entityManager,但要使用的特定绑定将是容器特定的(JBoss 、Glassfish、Weblogic 等)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      相关资源
      最近更新 更多