web-dev-qa-db-fra.com

Comment démarrer une transaction dans JPA à l'aide de entityManager

J'ai commencé à travailler sur une application qui utilise des services Web Spring, Hibernate, JPA et SOAP. Il est maintenant nécessaire que certaines requêtes soient exécutées dans une transaction. En cas d'échec, la transaction doit être annulée. 

Le code dans la couche dao est le suivant:

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(){
             }

             }

    }

Lorsqu'il exécute tx = em.getTransaction(), il génère l'erreur suivante:

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

Les autres propriétés liées à la transaction sont les suivantes:

<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>

Lorsque j'utilise session.beginTransaction() et session.getTransaction().commit(), cela fonctionne correctement.

Cependant, je veux le remplacer par une transaction de entityManager. Alors qu'est-ce qui devrait être fait?

5
azaveri7

Essayez d’injecter EntityManagerFactory puis de créer manuellement EntityManager:

@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

L'instance EntityManager renvoyée par @PersistenceContext est toujours un EntityManager géré par conteneur. Et EntityManager géré par conteneur sont toujours des EntityManagers JTA et, par conséquent, leur cycle de vie est géré par le conteneur. Je suppose qu’à présent, il est logique de dire pourquoi il est illégal d’appeler getTransaction () sur eux . Cela pourrait aider

1
userJ
0
yaswanth

Ajoutez une propriété hibernate.jta.allowTransactionAccess avec la valeur true et vous devriez être autorisé à l'utiliser manuellement. Bien que ce ne soit pas une bonne pratique de mélanger vos stratégies, faire gérer du code par JTA, certains manuellement.

0
coladict