Spring Hibernate - Tidak dapat memperoleh sesi transaksi-sinkronis untuk utas saat ini

106

Saya membuat aplikasi dengan musim semi + hibernasi, tetapi saya selalu mendapatkan kesalahan ini. Ini adalah aplikasi pertama saya dengan hibernate, saya membaca beberapa panduan tetapi saya tidak dapat menyelesaikan masalah ini. Dimana saya melakukan kesalahan?

Ini adalah kode aplikasi saya

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
sumber
3
Apakah Anda mencoba menambahkan @Transactional ke metode pembuatan DAO?
Yohanes
1
Anda lupa mendeklarasikan HibernateTransactionManager, dan membuat metode menggunakan Hibernate transactional.
JB Nizet
@itachi tidak benar, sessionFactory.openSession()transaksi akan dinonaktifkan. Karena mereka bukanlah sesi yang sama. > Tambahkan anotasi @Transactional of spring di layanan kelas @Patrikoko benar! lihat pertanyaan ini: stackoverflow.com/questions/15620355/… contoh:@Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = {java.lang.Exception.class})
nvnpnco

Jawaban:

200

Anda harus mengaktifkan dukungan transaksi ( <tx:annotation-driven>atau @EnableTransactionManagement) dan menyatakan yang transactionManagerdan harus bekerja melaluiSessionFactory .

Anda harus menambahkan @Transactionalke dalam@Repository

Dengan @Transactionaldi@Repository Spring dapat menerapkan dukungan transaksional ke dalam repositori Anda.

StudentKelas Anda tidak memiliki penjelasan @ javax.persistence. * Bagaimana @Entity, saya mengasumsikan Konfigurasi Pemetaan untuk kelas itu telah ditentukan melalui XML.

Manuel Jordan
sumber
1
Tolong, Bisakah Anda menulis kode aplikasi karena tidak berfungsi .. Ini adalah aplikasi pertama saya dengan Hibernate
Alex
3
Anotasi yang setara dengan <tx: annotation-driven> adalah @EnableTransactionManagement
Anand Rockzz
5
Selain itu, pastikan Anda menggunakan org.springframework.transaction.annotation.Transactional, bukan javax.persistance.Transactional
imnd_neel
Cheers sobat, saya tidak percaya saya melewatkan anotasi ini :).
Boldbayar
1
Saya telah mencoba berjam-jam untuk membuat transaksi bekerja dan akhirnya saya menggunakan @EnableTransactionManagement daripada <tx: annotation-driven> dan semuanya bekerja dengan sempurna. Saya tidak bisa cukup berterima kasih kepada Anda Manuel
Abu Sulaiman
38

Saya memiliki masalah yang sama, tetapi di kelas yang bukan bagian dari lapisan layanan. Dalam kasus saya, manajer transaksi hanya diperoleh dari konteks dengan getBean()metode, dan kelas termasuk dalam lapisan tampilan - proyek saya menggunakan OpenSessionInViewteknik.

The sessionFactory.getCurrentSession()metode, telah menyebabkan pengecualian yang sama sebagai penulis yang. Solusi bagi saya cukup sederhana.

Session session;

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

Jika getCurrentSession()metode ini gagal, openSession()trik seharusnya berhasil.

itachi
sumber
ketika memutakhirkan dari Hibernate3 ke Hibernate5, saya harus mengubah kode dari SessionFactoryUtils.getSession () ke sessionFactory.getCurrentSession (). Menemukan kesalahan yang sama pada saat itu.
pengguna811433
2
Ini memberikan perilaku yang sangat buruk bahwa jika sessionFactory.getCurrentSession();berhasil maka sesi tidak boleh ditutup tetapi jika sessionFactory.openSession();berhasil harus ditutup
Richard Tingle
1
Setuju @RichardTingle. Sepertinya openSession adalah peretasan untuk melewati pengecualian. Apa yang harus menjadi solusi menganggur untuk ini?
Praveen Shendge
@Praveen apa yang sebenarnya saya lakukan adalah memiliki layanan menerima lambda yang Function<Session,T>berarti "jika saya memiliki sesi, saya akan menggunakannya untuk melakukan X". Kemudian metode menangani penyediaan dan (Jika perlu) mencabut akses sesi, dan hanya mengembalikan T. Jadi konsumen eksternal layanan tidak pernah benar-benar mendapatkan sesi mereka
Richard Tingle
Ini membuat program saya berjalan tanpa ada tanda error. Saya khawatir tidak ada transaksi di beberapa kueri yang dibuat dengan cara ini, yang berarti saya berisiko mengembalikan hasil yang tidak konsisten?
Ole VV
13

Tambahkan anotasi @Transactional of spring di layanan kelas

Patrikoko
sumber
3

Di xyz.DAOImpl.java Anda

Lakukan langkah-langkah berikut:

// Langkah-1: Setel pabrik sesi

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

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

// Langkah-2: Cobalah untuk mendapatkan sesi saat ini, dan tangkap pengecualian HibernateException.


// Langkah-3: Jika ada pengecualian HibernateException, true untuk mendapatkan openSession.

try 
{
    //Step-2: Implementation
    session = sessionFactory.getCurrentSession();
} 
catch (HibernateException e) 
{
    //Step-3: Implementation
    session = sessionFactory.openSession();
}
ArunDhwaj IIITH
sumber
Hai! Bukankah Hibernate seharusnya melakukan itu sendiri?
Chris
2

Saya menambahkan konfigurasi ini di web.xml dan berfungsi dengan baik untuk saya!

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

Selain itu, jawaban dengan peringkat tertinggi memberi saya petunjuk untuk mencegah aplikasi panik saat pertama kali dijalankan.

何德福
sumber
1
Saya menggunakan springMVC 4 dan Hibernate 5
何德福
2

Anda perlu mengizinkan transaksi ke metode DAO Anda. Menambahkan,

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

atas metode dao Anda. Dan @Transactionalharus dari paket:

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

Saya mengalami kesalahan ini juga karena di file tempat saya menggunakan @Transactional anotasi, saya mengimpor kelas yang salah

import javax.transaction.Transactional; 

Alih-alih javax, gunakan

import org.springframework.transaction.annotation.Transactional; 
pintu coklat
sumber
1

Solusi saya adalah (menggunakan Spring) meletakkan metode yang gagal di dalam metode lain yang membuat dan melakukan transaksi.

Untuk melakukan itu saya pertama kali menyuntikkan berikut ini:

@Autowired
private PlatformTransactionManager transactionManager;

Dan akhirnya melakukan ini:

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

    oldMethod();

    transactionManager.commit(transaction);
}
Aliuk
sumber
1

@Transactional =javax.transaction.Transactional. Taruh di samping @Repository.

Alter Hu
sumber
0

Konfigurasi saya seperti ini. Saya memiliki QuartzJob , Service Bean, dan Dao. seperti biasa itu dikonfigurasi dengan LocalSessionFactoryBean (untuk hibernate), dan SchedulerFactoryBean untuk kerangka Quartz. saat menulis pekerjaan Quartz, saya secara tidak sengaja memberi anotasi dengan @ Service , saya seharusnya tidak melakukannya karena saya menggunakan strategi lain untuk menghubungkan QuartzBean menggunakan AutowiringSpringBeanJobFactory dengan memperpanjang SpringBeanJobFactory .

Jadi yang sebenarnya terjadi adalah karena Quartz Autowire, TX disuntikkan ke Job Bean dan pada saat yang sama Tx Context ditetapkan berdasarkan anotasi @ Service dan karenanya TX tidak sinkron !!

Saya berharap ini membantu mereka yang solusi di atas benar-benar tidak menyelesaikan masalah. Saya menggunakan Spring 4.2.5 dan Hibernate 4.0.1,

Saya melihat bahwa di utas ini ada saran yang tidak perlu untuk menambahkan anotasi @ Transaksional ke DAO (@ Repository ), itu adalah saran yang tidak berguna karena @ Repositori memiliki semua yang diperlukannya tidak harus secara khusus mengatur @ transaksional itu pada DAO, sebagai DAO dipanggil dari layanan yang telah diinjeksi oleh @Trasancational . Saya harap ini bisa membantu orang-orang yang menggunakan Quartz, Spring dan Hibernate bersama-sama.

SANJAY GAUTAM
sumber
0

Tambahkan transaction-managerke Anda <annotation-driven/>di spring-servlet.xml:

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

Periksa kelas dao Anda. Ini harus seperti ini:

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

Dan anotasi:

@Transactional
@Repository
Evgeniya O
sumber
0

Saya mengalami masalah yang sama dan akhirnya menemukan bahwa <tx:annotaion-driven />itu tidak didefinisikan dalam kelas beranotasi di [dispatcher]-servlet.xmlmana elemen pemindaian komponen diaktifkan @service.

Sederhananya <tx:annotaion-driven />dengan elemen pemindaian komponen, masalah tersebut menghilang.

Lee
sumber
0

Masalah serupa saya diperbaiki dengan 2 pendekatan di bawah ini.

1) Melalui penanganan transaksi secara manual:

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

2) Beri tahu Spring untuk membuka dan mengelola transaksi untuk Anda di web.xmlfilter Anda dan Pastikan untuk menggunakan @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
sumber
0

Terima kasih atas komentar mannedear. Saya menggunakan springmvc dan dalam kasus saya, saya harus menggunakan sebagai

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

dan saya juga menambahkan konteks pegas ke pom.xml dan berhasil

Lam
sumber
0

Saya memiliki masalah yang sama. Saya menyelesaikannya dengan melakukan hal berikut:

  1. Tambahkan baris ini ke dispatcher-servletfile:

    <tx:annotation-driven/>

    Periksa <beans>bagian di atas di file yang sama. Kedua baris ini harus ada:

    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. Juga pastikan Anda menambahkan @Repositorydan di @Transactionalmana Anda menggunakan sessionFactory.

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

Di kelas ini di atas @Repositoryhanya menempatkan satu penjelasan lagi @Transactionalitu akan berfungsi. Jika berhasil, balas kembali ( Y/ N):

@Repository
@Transactional
public class StudentDAOImpl implements StudentDAO
sunil jaiswal
sumber
1
Selamat datang di SO. Silakan baca Bagaimana cara menulis jawaban yang baik . Dalam SO tidak ada kebiasaan menjawab Y / T. Jika jawaban Anda berhasil untuk orang yang akan mereka tandai sebagai diterima. Jawaban yang membantu mungkin juga disukai.
Sri9911