Spring Hibernate - Transaktionssynchronisierte Sitzung für aktuellen Thread konnte nicht abgerufen werden

105

Ich habe eine Anwendung mit spring + hibernate erstellt, erhalte jedoch immer diesen Fehler. Dies ist meine erste Anwendung im Ruhezustand. Ich habe einige Anleitungen gelesen, kann dieses Problem jedoch nicht lösen. Wo mache ich falsch?

Dies ist der Code meiner Bewerbung

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)

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

studentDAO.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)
);
Alex
quelle
3
Haben Sie versucht, Ihrer DAO-Erstellungsmethode ein @Transactional hinzuzufügen?
John
1
Sie haben vergessen, einen HibernateTransactionManager zu deklarieren und die Methode mithilfe von Hibernate-Transaktionen durchzuführen.
JB Nizet
@itachi ist nicht korrekt, sessionFactory.openSession()die Transaktion wird deaktiviert. Weil sie nicht dieselbe Sitzung sind. > Fügen Sie die Anmerkung @Transactional of spring in den Klassendienst @Patrikoko ein! siehe diese Frage: stackoverflow.com/questions/15620355/… Beispiel:@Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = {java.lang.Exception.class})
nvnpnco

Antworten:

200

Sie müssen aktivieren Sie die Transaktionsunterstützung ( <tx:annotation-driven>oder @EnableTransactionManagement) und erklären das , transactionManagerund es sollte durch die Arbeit SessionFactory.

Sie müssen @Transactionalin Ihre hinzufügen@Repository

Mit @Transactionalin your @RepositorySpring können Sie Transaktionsunterstützung in Ihrem Repository anwenden.

Ihre StudentKlasse hat keine @ javax.persistence. * Anmerkungen wie @Entity, ich gehe davon aus, dass die Zuordnungskonfiguration für diese Klasse über XML definiert wurde.

Manuel Jordan
quelle
1
Bitte, können Sie den Code der Anwendung schreiben, weil es nicht funktioniert. Dies ist meine erste Anwendung mit Hibernate
Alex
3
Annotation-Äquivalent von <tx: annotation-powered> ist @EnableTransactionManagement
Anand Rockzz
5
Stellen Sie außerdem sicher, dass Sie org.springframework.transaction.annotation.Transactional verwenden, nicht javax.persistance.Transactional
imnd_neel
Prost Kumpel, ich kann nicht glauben, dass ich diese Anmerkung verpasst habe :).
Boldbayar
1
Ich habe stundenlang versucht, die Transaktion zum Laufen zu bringen, und schließlich habe ich @EnableTransactionManagement anstelle von <tx: annotation-powered> verwendet, und alles funktioniert perfekt. Ich kann Ihnen nicht genug danken Manuel
Abu Sulaiman
38

Ich hatte das gleiche Problem, aber in einer Klasse, die nicht Teil der Serviceschicht war. In meinem Fall wurde der Transaktionsmanager einfach durch die getBean()Methode aus dem Kontext abgerufen , und die Klasse gehörte zur Ansichtsebene - mein Projekt verwendet OpenSessionInViewTechnik.

Die sessionFactory.getCurrentSession()Methode hat dieselbe Ausnahme verursacht wie die des Autors. Die Lösung war für mich ziemlich einfach.

Session session;

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

Wenn die getCurrentSession()Methode fehlschlägt, openSession()sollte der den Trick machen.

itachi
quelle
Beim Upgrade von Hibernate3 auf Hibernate5 musste ich den Code von SessionFactoryUtils.getSession () in sessionFactory.getCurrentSession () ändern. Kam zu diesem Zeitpunkt auf den gleichen Fehler.
user811433
2
Dies gibt das wirklich böse Verhalten, dass, wenn sessionFactory.getCurrentSession();erfolgreich, die Sitzung nicht geschlossen werden sollte, aber wenn sessionFactory.openSession();erfolgreich ist, muss sie geschlossen werden
Richard Tingle
1
Stimmen Sie @RichardTingle zu. OpenSession scheint ein Hack zu sein, um die Ausnahme zu umgehen. Was sollte die Leerlauflösung dafür sein?
Praveen Shendge
@Praveen Was ich tatsächlich getan habe, war, dass ein Dienst ein Lambda akzeptiert, Function<Session,T>was bedeutet "Wenn ich eine Sitzung hätte, würde ich es verwenden, um X zu tun". Dann behandelt die Methode die Bereitstellung und (falls erforderlich) die Bereitstellung der Sitzung und gibt nur das T zurück. Externe Verbraucher des Dienstes erhalten also nie eine Sitzung in die Hände
Richard Tingle,
Dadurch lief mein Programm ohne Anzeichen eines Fehlers. Ich mache mir Sorgen, dass ich keine Transaktion für mehrere auf diese Weise erstellte Abfragen habe. Was bedeutet, dass ich das Risiko habe, inkonsistente Ergebnisse zurückzugeben?
Ole VV
13

Fügen Sie die Annotation @Transactional of spring zum Klassendienst hinzu

Patrikoko
quelle
3

In Ihrer xyz.DAOImpl.java

Führen Sie die folgenden Schritte aus:

// Schritt 1: Sitzungsfactory einstellen

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

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

// Schritt 2: Versuchen Sie, die aktuelle Sitzung abzurufen und die HibernateException-Ausnahme abzufangen.


// Schritt 3: Wenn es eine HibernateException-Ausnahme gibt, dann true, um openSession zu erhalten.

try 
{
    //Step-2: Implementation
    session = sessionFactory.getCurrentSession();
} 
catch (HibernateException e) 
{
    //Step-3: Implementation
    session = sessionFactory.openSession();
}
ArunDhwaj IIITH
quelle
Hallo! Soll Hibernate das nicht alleine tun?
Chris
2

Ich habe diese Konfiguration in web.xml hinzugefügt und es funktioniert gut für mich!

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

Darüber hinaus gibt mir die am besten bewertete Antwort Hinweise, um zu verhindern, dass die Anwendung beim ersten Durchlauf in Panik gerät.

何德福
quelle
1
Ich benutze springMVC 4 und Hibernate 5
何德福
2

Sie müssen die Transaktion für Ihre DAO-Methode zulassen. Hinzufügen,

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

über Ihre Dao-Methoden. Und @Transactionalsollte aus dem Paket sein:

org.springframework.transaction.annotation.Transactional
RahuL Sharma
quelle
1

Ich hatte auch diesen Fehler, weil ich in der Datei, in der ich @Transactional Annotation verwendet habe, die falsche Klasse importiert habe

import javax.transaction.Transactional; 

Verwenden Sie anstelle von Javax

import org.springframework.transaction.annotation.Transactional; 
Browndoor
quelle
1

Meine Lösung bestand darin, (mithilfe von Spring) die fehlgeschlagene Methode in eine andere Methode zu integrieren, mit der die Transaktion erstellt und festgeschrieben wird.

Dazu habe ich zuerst folgendes injiziert:

@Autowired
private PlatformTransactionManager transactionManager;

Und schließlich tat dies:

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

    oldMethod();

    transactionManager.commit(transaction);
}
Aliuk
quelle
1

@Transactional =javax.transaction.Transactional. Stell es einfach daneben @Repository.

Alter Hu
quelle
0

Meine Konfiguration war so. Ich hatte einen QuartzJob , eine Service Bean und Dao. Wie üblich wurde es mit LocalSessionFactoryBean (für den Ruhezustand) und SchedulerFactoryBean für das Quartz-Framework konfiguriert. während die Arbeit Quartz schreiben, kommentierte ich versehentlich es mit @ - Service , sollte ich das getan haben , nicht , weil ich eine andere Strategie wurde mit der verdrahten QuartzBean mit AutowiringSpringBeanJobFactory erstreckt SpringBeanJobFactory .

Was also tatsächlich geschah, war, dass TX aufgrund von Quartz Autowire in die Job Bean injiziert wurde und gleichzeitig der Tx-Kontext aufgrund der @ Service- Annotation festgelegt wurde und daher der TX nicht mehr synchron war !!

Ich hoffe, es hilft denen, für die die oben genannten Lösungen das Problem wirklich nicht gelöst haben. Ich habe Spring 4.2.5 und Hibernate 4.0.1 verwendet.

Ich sehe , dass in diesem Thread @ es ein unnötiger Vorschlag hinzuzufügen , ist Transactional Anmerkung zu dem DAO (@ Repository ), das ist eine nutzlose Vorschlag Ursache @ Repository hat alles , was es nicht speziell festgelegt haben muss müssen , dass @ Transaktions auf DAOs, wie die DAOs von den Diensten aufgerufen werden, die bereits von @Trasancational injiziert wurden . Ich hoffe, dass dies hilfreiche Leute sein können, die Quarz, Frühling und Winterschlaf zusammen verwenden.

SANJAY GAUTAM
quelle
0

Fügen Sie transaction-managerIhrer <annotation-driven/>in spring-servlet.xml hinzu:

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

Überprüfen Sie Ihre Dao-Klasse. Es muss so sein:

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

Und Anmerkungen:

@Transactional
@Repository
Evgeniya O.
quelle
0

Ich bin auf dasselbe Problem gestoßen und habe schließlich herausgefunden, dass das <tx:annotaion-driven />nicht in der Klasse annotiert ist, in der [dispatcher]-servlet.xmldas Komponenten-Scan-Element aktiviert ist @service.

Einfach zusammengesetzt <tx:annotaion-driven />mit dem Komponenten-Scan-Element, verschwand das Problem.

Lee
quelle
0

Mein ähnliches Problem wurde mit weniger als 2 Ansätzen behoben.

1) Durch manuelle Abwicklung von Transaktionen:

Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
UserInfo user = (UserInfo) session.get(UserInfo.class, 1);
tx.commit();

2) Weisen Sie Spring an, Transaktionen in Ihren web.xmlFiltern für Sie zu öffnen und zu verwalten, und stellen Sie sicher, dass Sie Folgendes verwenden @Repository @Transactional:

<filter>
  <filter-name>hibernateFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
  <init-param>
    <param-name>sessionFactory</param-name>
    <param-value>session.factory</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>hibernateFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
Jajikanth pydimarla
quelle
0

Danke für den Kommentar von mannedear. Ich benutze springmvc und in meinem Fall muss ich als verwenden

@Repository
@Transactional
@EnableTransactionManagement
public class UserDao {
...
}

und ich füge auch pom.xml spring-context hinzu und es funktioniert

Lam
quelle
0

Ich hatte das gleiche Problem. Ich habe es folgendermaßen gelöst:

  1. Fügen Sie diese Zeile zur dispatcher-servletDatei hinzu:

    <tx:annotation-driven/>

    Überprüfen Sie den obigen <beans>Abschnitt in derselben Datei. Diese beiden Zeilen müssen vorhanden sein:

    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation= "http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
  2. Stellen Sie außerdem sicher, dass Sie hinzugefügt haben @Repositoryund @Transactionalwo Sie verwenden sessionFactory.

    @Repository
    @Transactional
    public class ItemDaoImpl implements ItemDao {
        @Autowired
        private SessionFactory sessionFactory;
Nimisha
quelle
-1

In dieser Klasse oben wurde @Repositorynur eine weitere Anmerkung platziert @Transactional, die funktioniert. Wenn es funktioniert, antworte zurück ( Y/ N):

@Repository
@Transactional
public class StudentDAOImpl implements StudentDAO
sunil jaiswal
quelle
1
Willkommen bei SO. Bitte gehen Sie durch Wie schreibe ich eine gute Antwort . In SO gibt es keinen Brauch, J / N zu beantworten. Wenn Ihre Antwort für die Person funktioniert, die markiert wird, gilt sie als akzeptiert. Eine hilfreiche Antwort könnte ebenfalls positiv bewertet werden.
Sri9911