Вопрос по ejb-3.0, java, persistence – JTA EntityManager не может использовать getTransaction ()

20

Как у меня есть следующий код в моем приложении не-EJB. Код работает.

@Override
public void saveItems(Collection<T> items) {
    synchronized (em) {
        EntityTransaction tx = em.getTransaction();
        try {
            tx.begin();
            for (T item : items) {
                saveItem_((Class<T>) null, item);
            }
            tx.commit();
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
        }
    }
}

В новом приложении я использую EJB3 + JSF и хотел бы повторно использовать библиотеку, содержащую приведенный выше код. Моя единица постоянства для нового приложения выглядит следующим образом:

  <persistence-unit name="myApp" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>MySQLConnection</jta-data-source>
  </persistence-unit>

Мое новое приложение выдает исключение, когда оно попадает в эту строку:

    EntityTransaction tx = em.getTransaction();

исключение:

A JTA EntityManager cannot use getTransaction()

Что достаточно ясно. Вопрос в том, как мне преобразовать мой код, чтобы транзакции управлялись контейнером. Предположительно, мои методы должны быть соответствующим образом аннотированы ... Вопрос в том, как?

Ваш Ответ

3   ответа
0

который работает для меня на Jboss EAP6 и Hibernate 4.2.18.Final.

Может сэкономить время для кого-то.

persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
         version="2.0">
<persistence-unit name="myApp" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/MySQLConnection</jta-data-source>
<properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
        <!--
        <property name="hibernate.show_sql" value="true" />
        -->
    </properties>
</persistence-unit>

Джава

 import javax.annotation.Resource;
 import javax.persistence.EntityManager;
 import javax.transaction.UserTransaction;

public class MyClass {
@PersistenceContext(unitName = "myApp")
protected EntityManager em;
@Resource
UserTransaction utx;

public void execute(..) throws Exception {
    try {
        utx.begin();
        em.remove(..);
        em.merge(..);
        em.persist(..);
        utx.commit();
    } catch (Exception ex) {
        try {
            utx.rollback();
        } catch (Exception re) {
            throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
        }
        throw ex;
    }
}

}

pom.xml

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
        <scope>provided</scope>
    </dependency>

ссылки по теме:

Управляемые приложениямиhttps://docs.oracle.com/cd/E19798-01/821-1841/bnbra/index.html

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

15

EntityTransaction используется с менеджером сущностей типа ресурса local. Если вы хотите использовать JTA, то должны использоватьUserTransaction интерфейс.

Из документации:EntityTransaction - Interface used to control transactions on resource-local entity managers. The EntityManager.getTransaction() method returns the EntityTransaction interface.

Edit: Добавлен псевдокод.

@Resource
private SessionContext sessionContext;

void execute(){

UserTransaction userTxn = sessionContext.getUserTransaction();

try{

 userTxn.begin();
 /**
  *  do-something
  */
 userTxn.commit();

  } catch(Throwable e){
   userTxn.rollback(); //-- Include this in try-catch 
  }
}   
@ downvoter Если вы не можете объяснить & amp; понять, не отрицайте без причины.
@rtcarlson Почему понизили рейтинг & amp; Я не подтвердил в своем сообщении, чтобы использоватьUserTransaction интерфейс.
@ Emerald214 Соответствующий код добавлен для ясности, надеюсь, это поможет решить проблему.
Вы должны предоставить полное решение.
так какое здесь решение?
5

рен в EJB и вы не используете специальные аннотации, транзакция откроется в первом введенном EJB-методе (это означает, что если EjbA вызывает EjbB и, в свою очередь, вызывает EjbC, во всех методах EJB будет использоваться только одна транзакция). ). Если вы хотите изменить способ управления транзакциями, посмотрите @Transaction.

Самый простой способ сделать откат - вызвать исключение, помеченное @ApplicationException (rollback = true).

Я могу ошибаться, но, судя по вашему коду, вы должны прочитать разницу между EXTENDED и NORMAL EntityManager. Похоже, вы используете расширенный em очень неловко (перемещение цикла из транзакции поможет вам окончательно избавиться).

Small edit: если вы попытаетесь использовать UserTransaction, как и в другом сообщении, вы получите ошибку, потому что стандартный EntityManager (который вы, вероятно, используете) использует так называемые CMT (Container Managed Transactions). Не трогайте его, если вы не понимаете три основных варианта (если вы хотите, я могу уточнить, но, честно говоря, вам это НЕ понадобится):

container managed EntityManager versus application managed EntityManager, container managed transactions versus application managed transactions, NORMAL EntityManager and EXTENDED EntityManager.

Похожие вопросы