Как получить entity manager или транзакцию в прослушивателе jpa

я использовал прослушиватель событий Hibernate, как PostDeleteEventListener, PostInsertEventListener, PostUpdateEventListener для выполнения некоторых операций во время вставки, удаления и обновления. Теперь я хотел бы использовать JPA listener для этого, потому что, если мне нравится переходить из спящего режима в любой другой поставщик JPA, мой слушатель должен работать. Hibernate слушатель дает мне event из которого я могу получить транзакцию и проверить, совершена ли она или откат. Прослушиватели JPA предоставляют мне только объект сущности. Теперь, как я могу получить транзакцию или сеанс или Entity manger в Слушатель JPA?? Заранее спасибо!! Я использую Jboss в качестве своего CMT.

3 ответов


Это не поддерживается с JPA 2.0.

в JPA 2.1 (планируется в Java EE 7) поставщик сохраняемости будет рассматривать прослушиватели сущностей как компоненты CDI в управляемой среде (например, сервер приложений JBoss). От предлагаемый окончательный проект спецификации JPA 2.1, стр. 96:

классы прослушивателя сущностей в средах Java EE поддерживают зависимость инъекция через контексты и API инъекции зависимостей (CDI) [ 10 ] Когда содержащий архив-это бобовый архив. Сущность слушателя класс, использующий инъекцию CDI, также может определять жизненный цикл методы обратного вызова, аннотированные PostConstruct и PreDestroy комментарии. Эти методы будут вызваны после того как впрыска принимала место и перед уничтожением экземпляра прослушивателя сущности соответственно

Итак, в JPA 2.1, если вы создаете производитель CDI, который предоставляет EntityManager (просто аннотируя поле @PersistenceContext с помощью @Produces), вы можете просто @ввести EntityManager в прослушиватель.

в то же время, я не знаю ни одного чистого или приятное решение. "Наименее худшая" вещь, о которой я могу думать, - это настроить EntityManager для привязки к JNDI, а затем получить его через поиск JNDI из прослушивателя.


в моем случае я использую этот код:

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

Это хорошо работает для меня.

код этого приложения доступен для загрузки по адресуhttps://bitbucket.org/macielbombonato/apolo

Я надеюсь, что это может помочь вам.


вы можете использовать все прослушиватель pre/post load, insert, update или delete в 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. С помощью настойчивости.XML конфигурационный файл.

наконец, вместо аннотаций можно использовать и развертывать XMl-файл сопоставления с приложением для указания прослушивателей по умолчанию. (На этот файл сопоставления ссылается persistence.XML-файл.) Но сущность может использовать аннотацию @ExcludeDefaultListeners, если она не хочет использовать прослушиватели по умолчанию.

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

В вашей настойчивости.XML-код:

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