Pourquoi ma transaction n'est-elle pas active? javax.persistance.TransactionRequiredException: Exécution d'une requête de mise à jour/suppression


J'ai une application Spring Web Service (Spring-WS) que j'essaie de configurer pour l'utiliser. La pile que j'utilise est la suivante

Spring 3
Spring-WS
JPA with Hibernate as the provider
JBoss 7.1*

, L'application est configurée comme suit:

Persistance.xml

<persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/myDataSource</jta-data-source>
        <non-jta-data-source>java:jboss/datasources/myDataSource</non-jta-data-source>
        <class>myPackage.MyClass</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>           
            <property name="hibernate.connection.autocommit" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="validate"/>
            <property name="hibernate.show_sql" value="false"/>
            <property name="hibernate.cache.use_second_level_cache" value="true"/>
            <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/>
            <property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider"/>
            <property name="hibernate.search.default.indexBase" value="./lucene/indexes"/>
            <property name="hibernate.search.default.batch.merge_factor" value="10"/>
            <property name="hibernate.search.default.batch.max_buffered_docs" value="10"/>
        </properties>
    </persistence-unit>

Printemps.xml-Gestionnaire d'entités et de transactions

<context:annotation-config/>

    <context:component-scan base-package="com.mypackage"/>

    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

    <!-- Live database entity and transaction managers -->
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        p:dataSource-ref="myDataSource">

        <property name="persistenceUnitName" value="myPersistenceUnit" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
        p:entityManagerFactory-ref="entityManagerFactory" />

    <tx:annotation-driven transaction-manager="transactionManager" />           

Web.xml Pour charger le printemps.fichier xml ci-dessus

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/app-config.xml
            /WEB-INF/spring.xml
            /WEB-INF/spring-datasources.xml
         </param-value>   
     </context-param>

Source de données Spring.xml

<jee:jndi-lookup id="myDataSource" jndi-name="java:jboss/datasources/myDataSource"/>

Dans ma classe DAO, j'ai la définition suivante pour le l'entityManager.

@PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="myPersistenceUnit")
protected EntityManager entityManager;

@Transactional
    public void updateProduct(Product product) {

        //  Save the document to the database
        update(product);
    }

La méthode de mise à jour ci-dessus appelle simplement une méthode générique avec un appel à entityManager.merge(object);

Maintenant, lorsque je teste ce qui précède, je trouve que cela fonctionne si je lis dans la base de données mais cela ne fonctionne pas si j'écris dans la base de données (c'est-à-dire créer ou mettre à jour). Si j'essaie d'écrire dans le j'obtiens l'exception suivante:

javax.persistence.TransactionRequiredException: Executing an update/delete query
   at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:310)
   at $Proxy96.executeUpdate(Unknown Source)

Je suppose que je peux lire dans la base de données, cela signifie que quelque chose ne va pas dans la configuration du gestionnaire de transactions. Des idées?

Modifier

OK je viens de relire ce qui précède et j'ai remarqué que le dernier bit est légèrement faux. L'exception que j'ai montrée ci-dessus ne se produit que si j'utilise JPQL pour émettre une instruction Update en utilisant entityManager.createQuery. Si j'essaie de mettre à jour l'entité en utilisant entityManager.merge() rien ne se passe réellement. Aucune exception n'est renvoyée mais la ligne n'est pas mise à jour.

Author: Sanne, 2012-06-13

2 answers

Lorsque vous marquez une méthode comme @Transactional, vous comptez sur JTA, mais - comme indiqué par altanis - vous définissez le type de transaction de votre unité de persistance comme RESOURCE_LOCAL qui n'est pas JTA.

1) Si vous souhaitez utiliser des transactions gérées par conteneur, modifiez le type de transaction, définissez votre source de données en tant que source de données JTA dans JBoss et remplacez la source de données non jta par la source de données jta

2) Si vous souhaitez gérer vos propres transactions, conservez la persistance.xml et la définition de la source de données telle qu'elle est, mais avant toute opération persist, merge, remove, démarrez une transaction en appelant entitymanager.getTransaction().begin () et à la fin de l'unité commerciale, appelez entitymanager.getTransaction().commit () ou entitymanager.getTransaction().rollback(). Dans ce cas, puisque vous gérez vous-même les transactions, il semble inutile de démarrer une transaction JTA avec @Transactional dans updateProduct().

 4
Author: Hasan Ceylan, 2012-10-05 21:06:56

Essayez de changer transaction-type="RESOURCE_LOCAL" en transaction-type="JTA" dans la persistance.XML. Vous devrez peut-être également supprimer l'élément de la persistance.XML.

 1
Author: Sebastian Łaskawiec, 2012-06-13 13:55:08