Spring Hibernate - не удалось получить сеанс, синхронизированный с транзакциями, для текущего потока

Я создал приложение с помощью spring + hibernate, но всегда получаю эту ошибку. Это мое первое приложение со спящим режимом, я прочитал несколько руководств, но не могу решить эту проблему. Где я делаю неправильно?

Это код моего приложения

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)

студент.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

студентDAO.java

package coreservlets;

import org.hibernate.SessionFactory;

public interface StudentDAO {

    public void setSessionFactory(SessionFactory sessionFactory);

    public void create(String name,Integer age);

}//StudentDAO

СтудентDAOImpl.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)
);

person Alex    schedule 05.10.2014    source источник
comment
Вы пытались добавить @Transactional в свой метод создания DAO?   -  person John    schedule 05.10.2014
comment
Вы забыли объявить HibernateTransactionManager и сделать метод с использованием Hibernate транзакционным.   -  person JB Nizet    schedule 05.10.2014
comment
@itachi неверен, sessionFactory.openSession() транзакция будет отключена. Потому что это не одна и та же сессия. › Добавьте аннотацию @Transactional of spring в класс обслуживания @Patrikko правильно! см. этот вопрос: stackoverflow.com/questions/15620355/ пример: @Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = {java.lang.Exception.class})   -  person nvnpnco    schedule 19.04.2017


Ответы (18)


Вы должны включить поддержку транзакций (<tx:annotation-driven> или @EnableTransactionManagement) и объявить transactionManager, и это должно работать через SessionFactory.

Вы должны добавить @Transactional в свой @Repository

С @Transactional в вашем @Repository Spring может применить поддержку транзакций в вашем репозитории.

В вашем классе Student нет аннотаций @javax.persistence.*, как @Entity, я предполагаю, что конфигурация сопоставления для этого класса была определена через XML.

person Manuel Jordan    schedule 05.10.2014
comment
Пожалуйста, можете ли вы написать код приложения, потому что оно не работает. Это мое первое приложение с Hibernate - person Alex; 05.10.2014
comment
Аннотационный эквивалент ‹tx:annotation-driven› — @EnableTransactionManagement. - person Anand Rockzz; 04.01.2015
comment
Кроме того, убедитесь, что вы используете org.springframework.transaction.annotation.Transactional, а не javax.persistance.Transactional. - person imnd_neel; 20.05.2016
comment
Ура, приятель, не могу поверить, что пропустил эту аннотацию :). - person Boldbayar; 01.07.2016
comment
Я часами пытался заставить транзакцию работать и, наконец, использовал @EnableTransactionManagement вместо ‹tx:annotation-driven›, и все работает отлично. Я не могу отблагодарить вас достаточно, Мануэль - person Abu Sulaiman; 27.02.2017
comment
это, вероятно, очевидно, но все же: @EnableTransactionManagement переходит в ваш класс конфигурации (тот, который аннотирован @Configuration) - person Jaroslav Záruba; 12.03.2018
comment
Это отлично сработало после добавления @EnableTransactionManagement и @Transactional в мой класс DAO. - person mannedear; 12.08.2018
comment
Вы, ребята, сэкономили мне 2 часа поиска..! - person Shaik Bajivali; 15.05.2021

У меня была такая же проблема, но в классе, который не был частью сервисного слоя. В моем случае менеджер транзакций был просто получен из контекста методом getBean(), а класс принадлежал слою представления — мой проект использует технику OpenSessionInView.

Метод sessionFactory.getCurrentSession() вызывает то же исключение, что и автор. Решение для меня было довольно простым.

Session session;

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

Если метод getCurrentSession() не работает, openSession() должен помочь.

person itachi    schedule 25.04.2016
comment
при обновлении с Hibernate3 до Hibernate5 мне пришлось изменить код с SessionFactoryUtils.getSession() на sessionFactory.getCurrentSession(). Наткнулся на ту же ошибку в то время. - person user811433; 20.07.2016
comment
Это дает действительно неприятное поведение: если sessionFactory.getCurrentSession(); завершается успешно, сеанс не должен быть закрыт, но если sessionFactory.openSession(); завершается успешно, он должен быть закрыт. - person Richard Tingle; 18.10.2017
comment
Согласен @RichardTingle. Похоже, openSession — это хак для обхода исключения. Каким должно быть простое решение для этого? - person Praveen Shendge; 11.10.2018
comment
@Praveen то, что я на самом деле сделал, это заставить службу принимать лямбда Function<Session,T>, что означает, что если бы у меня был сеанс, я бы использовал его для выполнения X. Затем метод обрабатывает инициализацию и (если необходимо) деинициализацию сеанса и просто возвращает T. Итак внешние потребители сервиса никогда не получают доступ к сеансу - person Richard Tingle; 14.10.2018
comment
Это заставило мою программу работать без признаков ошибки. Меня беспокоит, что у меня нет транзакции по нескольким запросам, созданным таким образом, а это значит, что я рискую вернуть противоречивые результаты? - person Ole V.V.; 13.07.2020

Добавьте аннотацию @Transactional spring в сервис класса.

person Patrikoko    schedule 16.12.2015

В вашем xyz.DAOImpl.java

Выполните следующие действия:

//Шаг-1: Установить фабрику сеансов

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

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

//Шаг 2: попытайтесь получить текущий сеанс и поймать исключение HibernateException.


//Шаг-3: Если есть какое-либо исключение HibernateException, то true для получения openSession.

try 
{
    //Step-2: Implementation
    session = sessionFactory.getCurrentSession();
} 
catch (HibernateException e) 
{
    //Step-3: Implementation
    session = sessionFactory.openSession();
}
person ArunDhwaj IIITH    schedule 20.05.2016
comment
Привет! Разве Hibernate не должен делать это сам по себе? - person Chris; 23.05.2020

Я добавил эту конфигурацию в web.xml, и у меня все работает!

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

Кроме того, ответ с самым высоким рейтингом дает мне подсказки, чтобы предотвратить панику приложения при первом запуске.

person 何德福    schedule 25.10.2017
comment
Я использую SpringMVC 4 и Hibernate 5. - person 何德福; 25.10.2017

Вам необходимо разрешить транзакцию для вашего метода DAO. Добавлять,

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

над вашими методами дао. А @Transactional должно быть из пакета:

org.springframework.transaction.annotation.Transactional
person RahuL Sharma    schedule 04.10.2018

У меня тоже была эта ошибка, потому что в файле, где я использовал аннотацию @Transactional, я импортировал неправильный класс

import javax.transaction.Transactional; 

Вместо javax используйте

import org.springframework.transaction.annotation.Transactional; 
person browndoor    schedule 23.12.2017

Мое решение состояло в том, чтобы (используя Spring) поместить метод, который терпит неудачу, в другой метод, который создает и фиксирует транзакцию.

Для этого я сначала ввел следующее:

@Autowired
private PlatformTransactionManager transactionManager;

И наконец сделал это:

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

    oldMethod();

    transactionManager.commit(transaction);
}
person Aliuk    schedule 17.01.2019

@Transactional =javax.transaction.Transactional. Поместите его рядом с @Repository.

person Alter Hu    schedule 28.12.2015

Моя конфигурация была такой. У меня были QuartzJob, Service Bean и Dao. как обычно, он был настроен с помощью LocalSessionFactoryBean (для спящего режима) и SchedulerFactoryBean для платформы Quartz. при написании задания Quartz я по ошибке аннотировал его @Service , мне не следовало этого делать, потому что я использовал другую стратегию для подключения QuartzBean с помощью AutowiringSpringBeanJobFactory расширение SpringBeanJobFactory.

Итак, что на самом деле происходило, так это то, что из-за Quartz Autowire TX вводился в Job Bean, и в то же время Tx Context устанавливался на основании аннотации @Service, и, следовательно, TX выпадал из синхронизировать !!

Я надеюсь, что это поможет тем, для кого приведенные выше решения действительно не решили проблему. Я использовал Spring 4.2.5 и Hibernate 4.0.1,

Я вижу, что в этой теме есть ненужное предложение добавить аннотацию @Transactional в DAO(@Repository), это бесполезное предложение, потому что @Repository< /strong> имеет все, что ему нужно, не нужно специально устанавливать этот @transactional для DAO, так как DAO вызываются из служб, которые уже внедрены @Trasancational< /сильный> . Я надеюсь, что это может быть полезно людям, которые используют Quartz, Spring и Hibernate вместе.

person SANJAY GAUTAM    schedule 13.02.2018

Добавьте transaction-manager к <annotation-driven/> в spring-servlet.xml:

<tx:annotation-driven transaction-manager="yourTransactionBeanID"/>
person Majid    schedule 01.06.2018

Проверьте свой класс дао. Должно быть так:

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

И аннотации:

@Transactional
@Repository
person Evgeniya O    schedule 06.06.2018

Я столкнулся с той же проблемой и, наконец, обнаружил, что <tx:annotaion-driven /> не был определен в [dispatcher]-servlet.xml, где элемент компонентного сканирования включил @service аннотированный класс.

Просто соедините <tx:annotaion-driven /> с элементом component-scan вместе, и проблема исчезнет.

person Lee    schedule 20.04.2017

Моя аналогичная проблема была исправлена ​​с помощью двух подходов ниже.

1) Через ручную обработку транзакций:

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

2) Скажите Spring открывать и управлять транзакциями для вас в ваших web.xml фильтрах и убедитесь, что вы используете @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>
person Jajikanth pydimarla    schedule 14.08.2017

В этом классе выше @Repository просто размещена еще одна аннотация @Transactional она будет работать. Если получится, ответьте (Y/N):

@Repository
@Transactional
public class StudentDAOImpl implements StudentDAO
person sunil jaiswal    schedule 30.09.2019
comment
Добро пожаловать в СО. Пожалуйста, прочитайте Как мне написать хороший ответ. В SO нет обычая отвечать Y/N. Если ваш ответ подходит человеку, которого он отметит, он считается принятым. Полезный ответ также может быть одобрен. - person Sri9911; 30.09.2019

Спасибо за комментарий mannedear. Я использую springmvc, и в моем случае я должен использовать как

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

и я также добавляю spring-context в pom.xml, и он работает

person Lam    schedule 16.05.2020

Я была такая же проблема. Я решил это, выполнив следующие действия:

  1. Добавьте эту строку в файл dispatcher-servlet:

    <tx:annotation-driven/>
    

    Проверьте выше раздел <beans> в том же файле. Эти две строки должны присутствовать:

    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. #P4# <блочная цитата>
    @Repository
    @Transactional
    public class ItemDaoImpl implements ItemDao {
        @Autowired
        private SessionFactory sessionFactory;
    
person Nimisha    schedule 12.06.2020

В моей таблице базы данных имя столбца не соответствует объекту Java (@Entity), что приводит к возникновению вышеуказанного исключения.

Эта проблема решается путем обновления таблицы соответствующим именем столбца.

person VNT    schedule 08.12.2020