web-dev-qa-db-fra.com

TransactionRequiredException Exécution d'une requête de mise à jour / suppression

Bonjour, j’utilise Hibernate JPA avec spring et mongodb et j’exécute mon application sur Glassfish-4.0.

Ma classe de service est:

@Component
public class Test {
    @PersistenceContext
    EntityManager em;
    EntityManagerFactory emf;

    @Transactional
    public String persist(Details details) {
        details.getUsername();
        details.getPassword();

        Query query = em.createNativeQuery("db.details.find(username="+details.getUsername()+"&password="+details.getPassword());

        em.getTransaction().begin();
        em.persist(details);
        em.getTransaction().commit();
        em.flush();
        em.clear();
        em.close();
        query.executeUpdate();
        System.out.println("Sucessful!");
        return "persist";        
    }
}

Et mon spring-context.xml est:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="com.javapapers.spring.mvc" />
    <context:annotation-config />
    <mvc:annotation-driven />
    <tx:annotation-driven transaction-manager="txManager" />
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="ogmTest"/>
    </bean>
    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    </bean>
</beans>

J'ai appliqué quelques modifications au code mais elles n'ont aucun effet. Quelqu'un peut-il m'aider s'il vous plaît à résoudre ce problème. Merci d'avance.

37
user41498

Je ne sais pas si cela aidera votre situation (c'est-à-dire si elle existe toujours), cependant, après avoir parcouru le Web à la recherche d'un problème similaire.

Je créais une requête native à partir d'un EntityManager de persistance pour effectuer une mise à jour.

Query query = entityManager.createNativeQuery(queryString);

Je recevais l'erreur suivante:

provoqué par: javax.persistence.TransactionRequiredException: exécution d'une requête de mise à jour/suppression

De nombreuses solutions suggèrent d'ajouter @Transactional à votre méthode. Le simple fait de faire cela n'a pas changé l'erreur.

Certaines solutions suggèrent de demander à EntityManager un EntityTransaction afin que vous puissiez appeler, commencer et vous engager vous-même. Cela jette une autre erreur:

provoqué par: Java.lang.IllegalStateException: il n'est pas autorisé à créer une transaction sur EntityManager partagé - utilisez plutôt des transactions Spring ou EJB CMT

J'ai ensuite essayé une méthode qui, selon la plupart des sites, est destinée à l'utilisation de gestionnaires d'entités gérées par l'application et non à celle gérée par conteneur (ce qui, selon moi, est Spring) et c'était joinTransaction().

Après avoir décoré la méthode par @Transactional, Puis appelé joinTransaction() sur l'objet EntityManager juste avant d'appeler query.executeUpdate(), la mise à jour de ma requête native a fonctionné.

J'espère que cela aide quelqu'un d'autre confronté à ce problème.

50
Drew Corbin

en tant que configuration XML, il est clair que vous allez utiliser une transaction à ressort. Assurez-vous que l’importation que vous utilisez pour @Transactional est "org.springframework.transaction.annotation.Transactional"

dans votre cas, il pourrait être "javax.transaction.Transactional"

à votre santé

Chetan Verma

25
Chetan Verma

Dans mon cas, je me suis trompé @Transaction importé. Le bon est:

org.springframework.transaction.annotation.Transactional

et notjavax.transaction.Transactional.

24
User-8017771

J'ai également rencontré le même problème lorsque je travaille avec Hibernate et Spring Jpa Data Repository. J'ai oublié de placer @Transactional Sur la méthode du référentiel de données Spring.

Cela fonctionne pour moi après l'annotation avec @Transactional.

15
Satya P

Pourquoi ne pas déménager @Transactional de la méthode au niveau de la classe? A travaillé pour moi dans des cas similaires, bien que je ne sois pas sûr à 100% de pourquoi.

5
mvmn

Ajoutez simplement @ Transactional au niveau de la méthode ou de la classe. Lorsque vous mettez à jour ou supprimez des enregistrements, vous devez conserver l’état de persistance de Transaction et @Transactional gère cela.

et importationorg.springframework.transaction.annotation.Transactional;

4
Deva

J'ai reçu cette exception lorsque j'essayais d'exécuter une requête UPDATE en bloc dans un gestionnaire d'entités non-JTA (ressource locale) dans Java SE. J'avais simplement oublié d'envelopper mon code JPQL dans

em.getTransaction().begin();

et

em.getTransaction().commit();
4
JL_SO

J'ai eu la même erreur.

Je viens d'ajouter l'annotation @ Transactional de javax.transaction.Transactional sur la méthode.

2
Akshay Pethani

Vous n'avez pas à vous soucier des transactions de début et de fin. Vous avez déjà appliqué l'annotation @Transactional, qui ouvre en interne la transaction lorsque votre méthode commence et se termine à la fin de votre méthode. Il est donc uniquement nécessaire de conserver votre objet dans la base de données.

 @Transactional(readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})

         public String persist(Details details){
             details.getUsername();
             details.getPassword();
             Query query = em.createNativeQuery("db.details.find(username= "+details.getUsername()+"& password= "+details.getPassword());

             em.persist(details);
             System.out.println("Sucessful!");
            return "persist";        
     }

EDIT: le problème semble être lié à votre fichier de configuration. Si vous utilisez JPA, votre fichier de configuration devrait avoir une configuration inférieure à la configuration

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory" />
<bean id="jpaAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
    p:database="Oracle" p:showSql="true" />
<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:persistenceUnitName="YourProjectPU"
    p:persistenceXmlLocation="classpath*:persistence.xml"
    p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter">
    <property name="loadTimeWeaver">
        <bean
            class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
    </property>
    <property name="persistenceProvider" ref="interceptorPersistenceProvider" />

</bean>
1
DeepInJava

Rien ne semblait fonctionner pour moi avant que je réalise que ma méthode avait été déclarée comme public final _ au lieu de public. L'erreur était causée par le mot clé final. Le supprimer a fait disparaître l'erreur.

1
Damir Olejar

Après avoir intégré Spring 4 à Hibernate 5 dans mon projet et rencontré ce problème, j'ai constaté que je pouvais empêcher l'erreur d'apparaître en modifiant le mode d'obtention de la session de sessionFactory.openSession() à sessionFactory.getCurrentSession(). la bonne façon de résoudre ce bogue peut être de continuer à utiliser la même session pour la transaction de liaison.opensession créera toujours une nouvelle session qui ne ressemble pas à la précédente contenant une transaction configed.using getCurrentSession et en ajoutant une propriété supplémentaire <property name="current_session_context_class">org.springframework.orm.hibernate5.SpringSessionContext</property> fonctionne bien pour moi.

0
何德福

J'étais confronté à la même erreur, malgré l'ajout d'une annotation @Transactional au niveau de la classe et l'importation d'org.springframework.transaction.annotation.Transactional.

Ensuite, j'ai réalisé que depuis que j'utilisais une requête hibernate, j'avais importé javax.persistence.Query au lieu d'import org.hibernate.query.Query. Par conséquent, ajouter import org.hibernate.query.Query. résolu le problème pour moi.

J'espère que cette idée aide quelqu'un.

0
Smitha

Face au même problème, j'ai tout simplement oublié d'activer la gestion des transactions avec le @EnableTransactionManagement annotation.

Ref:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html

0
Jonathan POIRIER

J'ai rencontré la même exception "TransactionRequiredException Exécution d'une requête de mise à jour/suppression" mais pour moi, c'est parce que j'ai créé un autre bean au printemps applicationContext.xml fichier avec le nom "transactionManager" faisant référence à "org.springframework.jms.connection.JmsTransactionManage r" mais il y avait un autre bean portant le même nom "transactionManager "faisant référence à" org.springframework.orm.jpa.JpaTransactionManager ". Ainsi, le bean JPA est surchargé par le bean JMS .

Après avoir renommé le nom de bean du JMS, le problème est résolu.

0
Abdullah

Message d'erreur lors de l'exécution du code:

javax.persistence.TransactionRequiredException: Exécution d'une requête de mise à jour/suppression

Commencez la transaction entityManager -> createNativeQuery -> exécuter la mise à jour -> transaction commitManManager pour l'enregistrer dans votre base de données. Cela fonctionne très bien pour moi avec Hibernate et postgresql.

Code

entityManager.getTransaction().begin();
Query query = entityManager.createNativeQuery("UPDATE tunable_property SET tunable_property_value = :tunable_property_value WHERE tunable_property_name = :tunable_property_name");
query.setParameter("tunable_property_name", tunablePropertyEnum.eEnableJobManager.getName());
query.setParameter("tunable_property_value", tunable_property_value);
query.executeUpdate();
entityManager.getTransaction().commit();
0
Gourab Paul