Spring Hibernate - Không thể có được Phiên đồng bộ hóa giao dịch cho chuỗi hiện tại


106

Tôi đã tạo một ứng dụng với spring + hibernate, nhưng tôi luôn gặp lỗi này. Đây là ứng dụng đầu tiên của tôi với chế độ ngủ đông, tôi đã đọc một số hướng dẫn nhưng tôi không thể giải quyết vấn đề này. Tôi đang làm sai ở đâu?

Đây là mã ứng dụng của tôi

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

3
Bạn đã thử thêm @Transactional vào phương thức tạo DAO của mình chưa?
John

1
Bạn quên khai báo HibernateTransactionManager và thực hiện phương thức bằng giao dịch Hibernate.
JB Nizet

@itachi không đúng, sessionFactory.openSession()giao dịch sẽ vô hiệu hóa. Vì chúng không cùng phiên. > Thêm chú thích @Transactional of spring trong dịch vụ lớp @Patrikoko là đúng! xem câu hỏi này: stackoverflow.com/questions/15620355/… ví dụ:@Transactional(readOnly = true, propagation = Propagation.REQUIRED, rollbackFor = {java.lang.Exception.class})
nvnpnco

Câu trả lời:


200

Bạn phải kích hoạt tính năng hỗ trợ giao dịch ( <tx:annotation-driven>hoặc @EnableTransactionManagement) và tuyên bố sự transactionManagervà nó cũng làm việc thông qua SessionFactory.

Bạn phải thêm @Transactionalvào@Repository

Với @Transactionalin your @RepositorySpring, bạn có thể áp dụng hỗ trợ giao dịch vào kho lưu trữ của mình.

StudentLớp của bạn không có chú thích @ javax.persistence. * Như thế nào @Entity, tôi giả sử rằng Cấu hình ánh xạ cho lớp đó đã được xác định thông qua XML.


1
Xin vui lòng, bạn có thể viết mã của ứng dụng bởi vì nó không works..This là ứng dụng đầu tiên của tôi với Hibernate
Alex

3
Chú thích tương đương với <tx: chú thích-driven> là @EnableTransactionManagement
Anand Rockzz

5
Ngoài ra, hãy đảm bảo rằng bạn sử dụng org.springframework.transaction.annotation.Transactional, không phải javax.persistance.Transactional
imnd_neel

Chúc mừng bạn đời, tôi không thể tin rằng tôi đã bỏ lỡ chú thích này :).
Boldbayar

1
Tôi đã cố gắng hàng giờ để giao dịch hoạt động và cuối cùng tôi đã sử dụng @EnableTransactionManagement thay vì <tx: annotation-driven> và mọi thứ hoạt động hoàn hảo. Tôi không thể cảm ơn đủ Manuel
Abu Sulaiman

38

Tôi đã gặp vấn đề tương tự, nhưng trong một lớp không phải là một phần của lớp dịch vụ. Trong trường hợp của tôi, trình quản lý giao dịch chỉ đơn giản được lấy từ ngữ cảnh bằng getBean()phương thức và lớp thuộc về lớp khung nhìn - dự án của tôi sử dụng OpenSessionInViewkỹ thuật.

Các sessionFactory.getCurrentSession()phương pháp, đã được gây ra ngoại lệ tương tự như tác giả là. Giải pháp cho tôi là khá đơn giản.

Session session;

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

Nếu getCurrentSession()phương pháp không thành công, openSession()bạn nên thực hiện thủ thuật.


khi nâng cấp từ Hibernate3 lên Hibernate5, tôi phải thay đổi mã từ SessionFactoryUtils.getSession () thành sessionFactory.getCurrentSession (). Đã xảy ra cùng một lỗi tại thời điểm đó.
user811433

2
Điều này cho phép các hành vi thực sự khó chịu mà nếu sessionFactory.getCurrentSession();thành công thì phiên này không nên được đóng lại nhưng nếu sessionFactory.openSession();thành công nó phải được đóng
Richard Tingle

1
Đồng ý @RichardTingle. Có vẻ như openSession là một hack để vượt qua ngoại lệ. Giải pháp nhàn rỗi nên là gì?
Praveen Shendge,

@Praveen những gì tôi thực sự đã làm là có một dịch vụ chấp nhận một lambda Function<Session,T>có nghĩa là "nếu tôi có một phiên, tôi sẽ sử dụng nó để làm X". Sau đó, tay cầm phương pháp trích lập dự phòng và (Nếu neccissary) hủy cấp phép phiên giao dịch, và chỉ trả về T. Vì vậy, người tiêu dùng bên ngoài của dịch vụ bao giờ thực sự có được bàn tay của họ trên một phiên
Richard Tingle

Điều này đã làm cho chương trình của tôi chạy mà không có dấu hiệu lỗi. Tôi lo lắng rằng tôi không có giao dịch qua nhiều truy vấn được tạo theo cách này, điều đó có nghĩa là tôi có nguy cơ trả về kết quả không nhất quán?
Ole VV

13

Thêm chú thích @Transactional of spring trong dịch vụ lớp


3

Trong xyz.DAOImpl.java của bạn

Thực hiện các bước sau:

// Bước-1: Đặt nhà máy phiên

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

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

// Bước-2: Cố gắng lấy phiên hiện tại và bắt ngoại lệ HibernateException.


// Bước-3: Nếu có bất kỳ ngoại lệ HibernateException nào, thì true để lấy openSession.

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

Chào! Không phải Hibernate phải tự làm điều đó sao?
Chris

2

Tôi đã thêm các cấu hình này trong web.xml và nó hoạt động tốt đối với tôi!

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

Ngoài ra, câu trả lời được xếp hạng cao nhất cung cấp cho tôi manh mối để ngăn ứng dụng bị hoảng loạn ở lần chạy đầu tiên.


1
Tôi đang sử dụng springMVC 4 và Hibernate 5
何德福

2

Bạn cần cho phép giao dịch với phương thức DAO của mình. Thêm vào,

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

qua các phương pháp dao của bạn. Và @Transactionalphải từ gói:

org.springframework.transaction.annotation.Transactional

1

Tôi cũng gặp lỗi này vì trong tệp mà tôi sử dụng @Transactional chú thích, tôi đã nhập sai lớp

import javax.transaction.Transactional; 

Thay vì javax, hãy sử dụng

import org.springframework.transaction.annotation.Transactional; 

1

Giải pháp của tôi là (sử dụng Spring) đặt phương thức bị lỗi bên trong một phương thức khác tạo và cam kết giao dịch.

Để làm điều đó, đầu tiên tôi đã tiêm những thứ sau:

@Autowired
private PlatformTransactionManager transactionManager;

Và cuối cùng đã làm điều này:

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

    oldMethod();

    transactionManager.commit(transaction);
}

1

@Transactional =javax.transaction.Transactional. Đặt nó ngay bên cạnh @Repository.


0

Cấu hình của tôi như thế này. Tôi đã có một QuartzJob , một Service Bean và Dao. như thường lệ, nó đã được cấu hình với LocalSessionFactoryBean (dành cho ngủ đông) và SchedulerFactoryBean dành cho khung Quartz. trong khi viết công việc Quartz, tôi đã chú thích nhầm nó với @ Service , đáng lẽ tôi không nên làm điều đó vì tôi đang sử dụng một chiến lược khác để kết nối QuartzBean bằng cách sử dụng AutowiringSpringBeanJobFactory mở rộng SpringBeanJobFactory .

Vì vậy, những gì thực sự đang xảy ra là do Quartz Autowire, TX đã được đưa vào Job Bean và đồng thời Tx Context đã được thiết lập nhờ chú thích @ Service và do đó TX không đồng bộ !!

Tôi hy vọng nó sẽ giúp ích cho những người mà các giải pháp trên thực sự không giải quyết được vấn đề. Tôi đang sử dụng Spring 4.2.5 và Hibernate 4.0.1,

Tôi thấy rằng trong chuỗi này có một đề xuất không cần thiết để thêm chú thích @ Giao dịch vào DAO (@ Kho lưu trữ ), đó là một gợi ý vô ích vì @ Kho lưu trữ có tất cả những gì nó cần không phải đặt đặc biệt @ giao dịch trên DAO, vì DAO được gọi từ các dịch vụ đã được @Trasancational đưa vào . Tôi hy vọng điều này có thể hữu ích với những người đang sử dụng Quartz, Spring và Hibernate cùng nhau.


0

Thêm transaction-managervào bạn <annotation-driven/>trong mùa xuân-servlet.xml:

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

0

Kiểm tra lớp dao của bạn. Nó phải như thế này:

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

Và chú thích:

@Transactional
@Repository

0

Tôi gặp phải vấn đề tương tự và cuối cùng phát hiện ra rằng <tx:annotaion-driven />không được xác định trong [dispatcher]-servlet.xmllớp phần tử quét thành phần kích hoạt @servicelớp chú thích.

Đơn giản chỉ cần kết <tx:annotaion-driven />hợp phần tử quét thành phần với nhau, vấn đề đã biến mất.


0

Vấn đề tương tự của tôi đã được khắc phục với 2 cách tiếp cận dưới đây.

1) Thông qua các giao dịch xử lý thủ công:

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

2) Yêu cầu Spring mở và quản lý các giao dịch cho bạn trong các web.xmlbộ lọc của bạn và Đảm bảo sử dụng @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>

0

Cảm ơn bình luận của mannedear. Tôi sử dụng springmvc và trong trường hợp của tôi, tôi phải sử dụng như

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

và tôi cũng thêm spring-context vào pom.xml và nó hoạt động


0

Tôi gặp vấn đề tương tự. Tôi đã giải quyết nó bằng cách sau:

  1. Thêm dòng này vào dispatcher-servlettệp:

    <tx:annotation-driven/>

    Kiểm tra <beans>phần trên trong cùng một tệp. Hai dòng này phải có mặt:

    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. Đồng thời đảm bảo rằng bạn đã thêm @Repository@Transactionalnơi bạn đang sử dụng sessionFactory.

    @Repository
    @Transactional
    public class ItemDaoImpl implements ItemDao {
        @Autowired
        private SessionFactory sessionFactory;

-1

Trong lớp này ở trên @Repositorychỉ cần đặt thêm một chú thích nữa là @Transactionalnó sẽ hoạt động. Nếu nó hoạt động, hãy trả lời lại ( Y/ N):

@Repository
@Transactional
public class StudentDAOImpl implements StudentDAO

1
Chào mừng đến với SO. Vui lòng xem qua Làm cách nào để viết một câu trả lời hay . Ở SO không có phong tục trả lời Y / N. Nếu câu trả lời của bạn phù hợp với người mà họ sẽ đánh dấu là đã được chấp nhận. Một câu trả lời hữu ích cũng có thể được ủng hộ.
Sri9911
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.