getCurrentSession及openSession正确打开方式(既管治病,还管死活)(针对hibernate4.3.2版本)

本文探讨了Spring事务管理和Hibernate集成的细节,特别是如何在Spring管理的对象内外使用getCurrentSession方法,以及在不同场景下可能遇到的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 接上篇我们看到在spring配置文件中,配置了事务,这样在使用getCurrentSession时,只需要在方法上加上@Transcational注解即可,需要注意的是,不管你执行什么操作,哪怕是查询,你依然需要事务的控制。这跟上一篇提到的只有进行DDL才需要事务是两个概念,getCurrentSession是spring管理的对象所共享的,在执行sql时,需要事务保证数据的一致性。这句话另外一层意思是,只有在spring管理的对象中,使用getCurrentSession才能获取到有效的且是spring控制事务的session。

 如果自己new对象,即便你把sessionFactory这个对象传入对象内部,使用getCurrentSession依然会报错。如果你根据报错去搜索,大致会搜索到这么一个结论,需要在hibernate.cfg.xml中添加一个属性

<property name="hibernate.current_session_context_class">thread</property>
 加上这个属性之后,使用 getCurrentSession确实可以获取到session对象,但此时,该对象并没有事务的控制,需要你自己去控制事务。接下来我们可以来看一些有意思的错误:

一、 不添加hibernate.current_session_context_class属性,并且在spring管理的对象之外使用getCurrentSession,代码及报错如下:无论get方法有没有@Transcational注解,都报相同的错误,可见@Transcational在这里并没有生效

public class Test1Dao {

    private SessionFactory sessionFactory;

    //通过构造器传入SessionFactory对象
    public Test1Dao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Transactional
    public List get() {
        try {
            Session session = sessionFactory.getCurrentSession();
            Transaction transaction = session.beginTransaction();
            List list = sessionFactory.getCurrentSession().createSQLQuery("SELECT  * from test_info").addEntity(TestInfo.class).list();
            transaction.commit();
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

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 com.ucredit.test.Test1Dao.get(Test1Dao.java:24)
	at com.ucredit.test.TestController.get(TestController.java:23)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

 二、加上hibernate.current_session_context_class属性,但是去掉Test1Dao中的事务,会发现,getCurrentSession需要事务的支持
public class Test1Dao {

    private SessionFactory sessionFactory;

    //通过构造器传入SessionFactory对象
    public Test1Dao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Transactional
    public List get() {
        try {
            Session session = sessionFactory.getCurrentSession();
//            Transaction transaction = session.beginTransaction();
            List list = sessionFactory.getCurrentSession().createSQLQuery("SELECT  * from test_info").addEntity(TestInfo.class).list();
//            transaction.commit();
            return list;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
org.hibernate.HibernateException: createSQLQuery is not valid without active transaction
	at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:352)
	at com.sun.proxy.$Proxy88.createSQLQuery(Unknown Source)
	at com.ucredit.test.Test1Dao.get(Test1Dao.java:26)
	at com.ucredit.test.TestController.get(TestController.java:23)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
 三、更新操作不生效,这个问题是针对openSession,这种方式获取的session并不会自动提交,需要执行flush方法才能够更新数据。
public class Test1Dao {

    private SessionFactory sessionFactory;

    //通过构造器传入SessionFactory对象
    public Test1Dao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void update() {
        Session session = sessionFactory.openSession();
        TestInfo testInfo = (TestInfo) session.createSQLQuery("SELECT  * from test_info").addEntity(TestInfo.class).uniqueResult();
        testInfo.setName("测试");
        session.update(testInfo);
    }
}
我在hibernate配置文件中设置了打印sql,但在控制台只看到了select语句,没有看到update,数据库也没有更新,但加上session.flush()后,执行结果如下:
Hibernate: SELECT  * from test_info
Hibernate: update test_info set key_id=?, name=? where id=?






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值