web-dev-qa-db-fra.com

Spring Hibernate - Impossible d'obtenir une session synchronisée par transaction pour le thread actuel

J'ai créé une application avec spring + hibernate, mais j'ai toujours cette erreur. Ceci est ma première application avec Hibernate, je lis quelques guides mais je ne peux pas résoudre ce problème. Où est-ce que je me trompe?

Ceci est le code de mon application

ott 05, 2014 4:03:06 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
Informazioni: Refreshing   org.springframework.context.support.ClassPathXmlApplicationContext@1eab16b: startup date  [Sun Oct 05 16:03:06 CEST 2014]; root of context hierarchy
ott 05, 2014 4:03:06 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
Informazioni: Loading XML bean definitions from class path resource [springConfig.xml]
ott 05, 2014 4:03:08 PM org.hibernate.annotations.common.reflection.Java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
ott 05, 2014 4:03:08 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.6.Final}
ott 05, 2014 4:03:08 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
ott 05, 2014 4:03:08 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
ott 05, 2014 4:03:09 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
ott 05, 2014 4:03:09 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
ott 05, 2014 4:03:09 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Exception in thread "main" org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.Java:134)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.Java:1014)
at coreservlets.StudentDAOImpl.create(StudentDAOImpl.Java:19)
at coreservlets.MainApp.main(MainApp.Java:14)

étudiant.Java

package coreservlets;

public class Student {

    private Integer id;
    private String name;
    private Integer age;

    public Integer getId(){return id;}//getId

    public void setId(Integer id){this.id=id;}//setId

    public String getName(){return name;}//getName

    public void setName(String name){this.name=name;}//setName

    public Integer getAge(){return age;}//getAge

    public void setAge(Integer age){this.age=age;}//setAge

}//Student

étudiantDAO.Java

package coreservlets;

import org.hibernate.SessionFactory;

public interface StudentDAO {

    public void setSessionFactory(SessionFactory sessionFactory);

    public void create(String name,Integer age);

}//StudentDAO

StudentDAOImpl.Java

package coreservlets;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class StudentDAOImpl implements StudentDAO {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory){
        this.sessionFactory=sessionFactory;
    }//setSessionFactory

    public void create(String name,Integer age){
        Session session=sessionFactory.getCurrentSession();
        Student student=new Student();
        student.setName(name);
        student.setAge(age);
        session.save(student);
    }//create

}//StudentDAOImpl

MainApp.Java

package coreservlets;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {

    public static void main(String[] args) {

        ApplicationContext context=new ClassPathXmlApplicationContext("springConfig.xml");

        StudentDAOImpl student=(StudentDAOImpl) context.getBean("studentDAOImpl");

        student.create("Alessandro", new Integer(33));


    }//main

}//MainApp

springConfig.xml

<?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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">

<context:annotation-config/>

<context:component-scan base-package="coreservlets"/>

<bean id="dataSource" class="org.Apache.commons.dbcp2.BasicDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/spring_hibernate"/>
  <property name="username" value="root"/>
  <property name="password" value="password"/>
  <property name="initialSize" value="5"/>
  <property name="maxTotal" value="10"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
    <value>
            hibernate.dialect=org.hibernate.dialect.MySQLDialect
    </value>
</property>

</bean>

</beans>

sql

create table student
(
id integer not null auto_increment,
name varchar(20) not null,
age integer not null,
primary key(id)
);
85
Alex

Vous devez activer la prise en charge de la transaction (<tx:annotation-driven> ou @EnableTransactionManagement) et déclarer la transactionManager et elle devrait fonctionner avec la SessionFactory.

Vous devez ajouter @Transactional dans votre @Repository

Avec @Transactional dans votre @Repository, Spring est en mesure d’appliquer un support transactionnel dans votre référentiel.

Votre classe Student n'a pas les annotations @ javax.persistence. * Comment @Entity, je suppose que la configuration de mappage pour cette classe a été définie via XML.

169
Manuel Jordan

J'ai eu le même problème, mais dans une classe qui ne faisait pas partie de la couche de service. Dans mon cas, le gestionnaire de transactions était simplement obtenu à partir du contexte par la méthode getBean() et la classe appartenait à la couche de vue - mon projet utilise la technique OpenSessionInView.

La méthode sessionFactory.getCurrentSession() a provoqué la même exception que celle de l'auteur. La solution pour moi était plutôt simple.

Session session;

try {
    session = sessionFactory.getCurrentSession();
} catch (HibernateException e) {
    session = sessionFactory.openSession();
}

Si la méthode getCurrentSession() échoue, la fonction openSession() devrait faire l'affaire.

31
itachi

Ajoutez l'annotation @Transactional de spring dans le service de classe

11
Patrikoko

Dans votre xyz.DAOImpl.Java

Effectuez les étapes suivantes:

// Étape 1: Définir la fabrique de session

@Resource(name="sessionFactory")
private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sf)
{
    this.sessionFactory = sf;
}

// Étape 2: essayez de récupérer la session en cours et attrapez l'exception HibernateException. 


// Étape 3: S'il existe une exception HibernateException, alors true pour obtenir openSession. 

try 
{
    //Step-2: Implementation
    session = sessionFactory.getCurrentSession();
} 
catch (HibernateException e) 
{
    //Step-3: Implementation
    session = sessionFactory.openSession();
}
2
ArunDhwaj IIITH

@Transactional = javax.transaction.Transactional le place juste à côté de @Repository 

1
Alter Hu

J'ai ajouté cette configuration dans web.xml et cela fonctionne bien pour moi!

<filter>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <param-name>sessionFactoryBeanName</param-name>
        <param-value>sessionFactory</param-value>
    </init-param>
    <init-param>
        <param-name>flushMode</param-name>
        <param-value>AUTO</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>OpenSessionInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

De plus, la réponse la mieux classée me donne des indices pour éviter toute panique lors de la première utilisation.

1
何德福

Vous devez autoriser la transaction sur votre méthode DAO . Ajouter,

@Transactional (readOnly = true, propagation = Propagation.NOT_SUPPORTED)

sur vos méthodes de dao . Et @Transactional devrait être du paquet,

org.springframework.transaction.annotation.Transactional

1
RahuL Sharma

J'ai aussi eu cette erreur parce que dans le fichier où j'ai utilisé l'annotation @Transactional, j'importais la mauvaise classe

import javax.transaction.Transactional; 

Au lieu de javax, utilisez

import org.springframework.transaction.annotation.Transactional; 
1
browndoor

Ma configuration était comme ça. J'ai eu un QuartzJob , un haricot de service et Dao. Comme d'habitude, il a été configuré avec LocalSessionFactoryBean (pour hibernate) et SchedulerFactoryBean pour Quartz. en écrivant le travail Quartz, je l'ai annoté par erreur avec @ Service , je n'aurais pas dû le faire car j'utilisais une autre stratégie pour câbler le QuartzBean using AutowiringSpringBeanJobFactory extend SpringBeanJobFactory

Donc, ce qui se passait, c’est que, à cause de Quartz Autowire, TX était injecté dans le Job Bean et qu’en même temps le contexte Tx était défini en vertu de @ Service annotation et que, par conséquent, le TX était désynchronisé! 

J'espère que cela aidera ceux pour qui les solutions ci-dessus n'ont pas vraiment résolu le problème. J'utilisais Spring 4.2.5 et Hibernate 4.0.1, 

Je vois que dans ce fil il y a une suggestion inutile d'ajouter @ Transactional annotation au DAO (@ Repository ), c'est une suggestion inutile. @ Repository a tout ce qu'il faut pour n'ont pas à définir spécialement ce @ transactionnel sur les DAO, car les DAO sont appelés à partir des services qui ont déjà été injectés par @Trasancational . J'espère que cela pourrait être utile aux personnes qui utilisent ensemble Quartz, Spring et Hibernate. 

0
SANJAY GAUTAM

J'ai rencontré le même problème et j'ai finalement découvert que le n'était pas défini dans le [dispatcher] -servlet.xml où composant-scan element enabled @service annotated class. 

Simplement mis avec l'élément composant-scan ensemble, le problème a disparu.

0
Lee

Ajoutez transaction-manager à votre <annotation-driven/> dans spring-servlet.xml:

<tx:annotation-driven transaction-manager="yourTransactionBeanID"/>
0
Majid

Ma solution était (en utilisant Spring) de mettre la méthode qui échoue dans une autre méthode qui crée et valide la transaction.

Pour ce faire, j'ai d'abord injecté ce qui suit:

@Autowired
private PlatformTransactionManager transactionManager;

Et finalement fait ceci:

public void newMethod() {
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    TransactionStatus transaction = transactionManager.getTransaction(definition);

    oldMethod();

    transactionManager.commit(transaction);
}
0
Aliuk

Mon problème similaire a été résolu avec moins de 2 approches.

  1. Traiter manuellement les transactions.

    Session session = sessionFactory.getCurrentSession ();

    Transaction tx = session.beginTransaction ();

    UserInfo user = (UserInfo) session.get (UserInfo.class, 1);

    tx.commit ();

  2. Dites à Spring d’ouvrir et de gérer les transactions pour vous dans vos filtres web.xml et d’assurer l’utilisation de @Repository @Transactional

    <filtre> <nom-filtre> hibernateFilter </ nom-filtre> <filter-class> org.springframework.orm.hibernate5.support.OpenSessionInViewFilter </ filter-class> <init-param> <nom du paramètre> sessionFactory <valeur-param> session.factory </ init-param> </ filter> <cartographie-filtre> <nom-filtre> hibernateFilter </ nom-filtre> <url-pattern>/* </ url-pattern> </ filter-mapping>

Désolé pour le formatage incorrect.

0
Jajikanth pydimarla

Vérifiez votre classe de dao. Ce doit être comme ça: 

Session session = getCurrentSession();
Query query = session.createQuery(GET_ALL);

Et annotations:

@Transactional
@Repository
0