wake-up-neo.com

So starten Sie eine Transaktion in JPA mit dem EntityManager

Ich habe begonnen, an einer Anwendung zu arbeiten, die Spring-, Hibernate-, JPA- und SOAP-Webservices verwendet. Nun müssen bestimmte Abfragen in einer Transaktion ausgeführt werden. Wenn eine fehlschlägt, sollte die gesamte Transaktion rückgängig gemacht werden. 

Der Code in der Dao-Schicht lautet wie folgt:

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import org.hibernate.Session;

    public class BillDAOImpl implements BillDao{

             @PersistenceContext(type = PersistenceContextType.EXTENDED)
             private EntityManager em;

             public boolean processBills() throws Exception{

             EntityTransaction tx = null;
             Session session = null;

             try{

                 session = em.unwrap(Session.class);
                 tx = em.getTransaction();

                 Bill bill = em.find(Bill.class, billId);

                 //session.beginTransaction();
                 tx.begin();
                 ...
                 ...
                 em.persist(bill);
                 ...
                 ...
                 em.merge(<other object>);
                 ...
                 ...
                 //session.getTransaction().commit();
                 tx.commit();
             } catch(){
             }

             }

    }

Wenn es tx = em.getTransaction() ausführt, gibt es folgenden Fehler:

Java.lang.IllegalStateException: Cannot execute getTransaction() on a container-managed EntityManager

Die anderen transaktionsbezogenen Eigenschaften lauten wie folgt:

<bean id="tuneEntityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:persistenceXmlLocation="classpath*:META-INF/tune-persistence.xml"
        p:persistenceUnitName="tunePersistenceUnit" p:loadTimeWeaver-ref="loadTimeWeaver"
        p:jpaVendorAdapter-ref="jpaVendorAdapter" p:jpaDialect-ref="jpaDialect"
        p:dataSource-ref="tuneDbDataSource">
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup
                </prop>
                <prop key="net.sf.ehcache.configurationResourceName">/${tune-db.ehcache.config.file}</prop>
                <prop key="hibernate.transaction.flush_before_completion">false</prop>              
                <prop key="hibernate.default_schema">${tune-db.schema}</prop>
                <prop key="org.hibernate.envers.default_schema">${tune-db.schema}</prop>
                <prop key="javax.persistence.validation.mode">${tune-db.data.validation}</prop>
                <prop key="hibernate.connection.isolation">3</prop>
                <prop key="hibernate.connection.release_mode">auto</prop>
                <prop key="hibernate.show_sql">${tune-db.hibernate.show-sql}</prop>
                <prop key="hibernate.format_sql">${tune-db.hibernate.format-sql}</prop>
            </props>
        </property>     
    </bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="tuneEntityManagerFactory" />
    </bean>

Wenn ich session.beginTransaction() und session.getTransaction().commit() verwende, funktioniert es korrekt.

Ich möchte es jedoch durch die Transaktion von entityManager ersetzen. Was soll dann gemacht werden?

5
azaveri7

Versuchen Sie, EntityManagerFactory zu injizieren und dann den EntityManager manuell zu erstellen:

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

public boolean processBills() throws Exception{

   EntityManager em = entityManagerFactory.createEntityManager();

   EntityTransaction tx = null;

   Session session = null;

   try{

       session = em.unwrap(Session.class);
       tx = em.getTransaction();
3
Maciej Kowalski

Die EntityManager-Instanz, die von @PersistenceContext zurückgegeben wird, ist immer ein vom Container verwalteter EntityManager. Container-verwaltete EntityManager sind immer JTA-EntityManagers, und daher wird ihr Lebenszyklus vom Container verwaltet. Ich denke jetzt macht es Sinn, warum es verboten ist, getTransaction () für sie aufzurufen. Dies könnte helfen

1
userJ
0
yaswanth

Fügen Sie eine hibernate.jta.allowTransactionAccess-Eigenschaft mit dem Wert true hinzu, und Sie sollten sie manuell verwenden dürfen. Obwohl es keine gute Praxis ist, Ihre Strategien zu mischen, lassen Sie Code von JTA verwalten, andere manuell.

0
coladict