Как взаимодействуют UserTransaction и EntityManager?

#jpa #jsf-2 #jpa-2.0

#jpa #jsf-2 #jpa-2.0

Вопрос:

Это академический вопрос; у меня нет сломанного кода в связи с этим. Я просто хочу расширить свое понимание того, что происходит под капотом.

Шаблон кода, который я использую (скопированный из книг и руководств) в моем JPA DAO для моих типичных веб-приложений JSF, в основном таков:

 public class someDAO {

    @PersistenceContext protected EntityManager   em;
    @Resource           private   UserTransaction utx;    

    public void persist(Entity entity) {
        try {
            utx.begin();
            em.persist(entity);
            utx.commit();
        } catch ( // gawd awful long list of possible exceptions ) 

        // etc
  

Итак, мои вопросы заключаются в следующем:

  1. Почему экземпляру EntityManager и экземпляру UserTransaction вводятся аннотации из двух, казалось бы, не связанных пакетов?

  2. Почему используются аннотации @Resource и @PersistenceContext, а не @ManagedProperty или, возможно, @Inject ?

  3. Как метод persist() получает доступ к объекту utx и взаимодействует с ним? Если я забуду вызов utx.begin(), диспетчер сущностей узнает об этом и выдает исключение. Должно быть, он находит объект UserTransaction каким-то волшебным образом. Не было бы лучшей архитектуры для определения интерфейса типа: em.persist(utx, entity)?

  4. Если utx является своего рода синглтоном — возможно ли одновременно открывать более одной UserTransaction?

Большое спасибо за любое обсуждение.

Комментарии:

1. Рассматривали ли вы EJB? EJB используют транзакции, управляемые контейнерами. Таким образом, вам не нужно беспокоиться об управлении транзакциями самостоятельно (и это избавляет ваши методы обслуживания от помех при попытке поймать).

2. Мои шаблоны кода изучены из таких книг, как Burns JSF 2. Я не возражаю против этого шаблона кода, потому что мне удалось ограничить все это одним абстрактным объектом DAO. Все мои конкретные DAO простираются от этого одного объекта, поэтому эта его часть (если применимо это слово) в значительной степени скрыта из виду. Но не из головы.

Ответ №1:

  1. Потому что UserTransaction является частью Java Transaction API (JTA), а EntityManager является частью Java Persistence API (JPA). JTA не является частью JPA. JPA использует сервисы, предоставляемые JTA.

  2. Не является ли ManagedProperty некоторой аннотацией, которая действительна только в классах, аннотированных с помощью @ManagedBean . Возможно, было сочтено, что лучше не вводить UserTransaction по-другому в управляемые компоненты.

  3. Поиск JNDI для активной транзакции. Зарезервированное имя, похоже, java:comp / UserTransaction. Одна реализация: http://www.java2s.com/Open-Source/Java-Document/Database-ORM/hibernate/org/hibernate/transaction/JTATransactionFactory.java.htm

  4. Это не какой-то синглтон, у вас может быть более одного. Но только один поток может быть активным.