您的位置:首页 > 运维架构

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

2018-01-23 15:06 323 查看
 接上篇我们看到在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
aa21
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=?


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: