hibernate.current_session_context_class 的各个取值的区别以及与Spring整合的问题
2016-07-25 09:30
525 查看
在非spring 环境下,
hibernate.current_session_context_class主要就是thread和jta 两个取值。
先看一段话:
[html] view
plain copy
What does sessionFactory.getCurrentSession() do? First, you can call it
as many times and anywhere you
like, once you get hold of your SessionFactory (easy thanks to
HibernateUtil). The getCurrentSession()
method always returns the "current" unit of work. Remember that we
switched the configuration option for this
mechanism to "thread" in hibernate.cfg.xml? Hence, the scope of the
current unit of work is the current Java
thread that executes our application. However, this is not the full
truth. A Session begins when it is first
needed, when the first call to getCurrentSession() is made. It is then
bound by Hibernate to the current
thread. When the transaction ends, either committed or rolled back,
Hibernate also unbinds the Session from
the thread and closes it for you. If you call getCurrentSession() again,
you get a new Session and can start a
new unit of work. This thread-bound programming model is the most
popular way of using Hibernate.
再看下面一段(来自Hibernate官网)
[html] view
plain copy
The easiest way to handle Sessions and transactions is Hibernate's automatic "current" Session management.
For a discussion of contextual sessions see 第 2.3 节 “上下文相关的会话(Contextual Session)”.
Using the "jta" session context, if there is no Hibernate Session associated with the current
JTA transaction, one will be started and associated with that JTA transaction the first time you call sessionFactory.getCurrentSession().
The Sessions retrieved via getCurrentSession() in the "jta" context are set
to automatically flush before the transaction completes, close after the transaction completes,
and aggressively release JDBC connections after each statement.
This allows the Sessions to be managed by the life cycle of the JTA transaction to which it is associated,
keeping user code clean of such management concerns.
Your code can either use JTA programmatically thr
11449
ough UserTransaction,
or (recommended for portable code) use the Hibernate Transaction API to set transaction boundaries.
If you run in an EJB container, declarative transaction demarcation with CMT is preferred.
[html] view
plain copy
使用getCurrentSession的代码举例:
[java] view
plain copy
SessionFactory sf = new Configuration().configure()
.buildSessionFactory();
Session s = null;
Transaction t = null;
try {
// 准备数据
UserModel um = new UserModel();
um.setUuid(9);
um.setUserId("id1");
um.setName("name1");
um.setAge(1);
s = sf.getCurrentSession();
t = s.beginTransaction();
s.save(um);
t.commit();
} catch (Exception err) {
err.printStackTrace();
t.rollback();
} finally {
}
1. 这两个值的相同点
对于sessionFactory.getCurrentSession()操作而言, 这两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作每次请求一个session。Hibernate
session的起始和终结由数据库事务的生存来控制。也就是说, 对于thread而言, 当执行getCurrentSession时, session创建并绑定到当前线程,当事务提交时, session就关闭了, 无须手动关闭session (openSession方法需要手动关闭session); jta与此类似,当执行getCurrentSession时, session创建并绑定到当前JTA context, 当事务提交时, session就关闭了, 无须手动关闭session 。
2. 不同点
org.hibernate.context.JTASessionContext - 当前session根据JTA上下文来跟踪和界定(即保存在JTA上下文中)。这和以前的仅支持JTA的方法是完全一样的。
org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线程来跟踪和界定(即保存在当前线程上下文的threadlocal变量中)。
在JDBC的独立应用程序中(非容器集成环境下),取值只能是thread, 否则程序会报以下错误:
[java] view
plain copy
org.hibernate.HibernateException: No TransactionManagerLookup specified
at org.hibernate.context.JTASessionContext.currentSession(JTASessionContext.java:81)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
at com.cvv.service.UserManager.exists(UserManager.java:16)
在J2EE容器的环境下, 可以使用thread, 也可以使用jta, 因为容器环境中一般会配置 TransactionManagerLookup。并且,如果没有配置 hibernate.current_session_context_class,但是有org.hibernate.transaction.TransactionManagerLookup的配置的情况下,Hibernate会采用org.hibernate.context.JTASessionContext,即jta。容器环境优先考虑jta方式。
在Spring环境中,
除了thread和jta两个值以外, Spring 增加了 org.springframework.orm.hibernate4.SpringSessionContext 这个值。
1. 当你使用Spring 声明式事务的时候 (@Transactional, tx标签 ...), @Transactional声明式事务管理 会创建一个 绑定了事务的session并把 该session放到SpringSessionContext 这个上下文中, 所以在使用声明式事务并且使用 getCurrentSession()这个方法的时候,只有从 SpringSessionContext
上下文中才能取到当前的session, 这就要求将 hibernate.current_session_context_class 这个值设置为org.springframework.orm.hibernate4.SpringSessionContext, 在spring 配置文件中, 在使用LocalSessionFactoryBean时会自动的设置这个值,
不需要你去设置, 所以在spring 配置中 hibernate.current_session_context_class 默认就是SpringSessionContext;
2. 如果你将 hibernate.current_session_context_class 设置成了 thread,并不是不可以, 而是代码需要做些修改:
因为使用Spring 声明式事务的时候, 绑定了事务的session被放置在了spring context中,而当前hibernate.current_session_context_class值为 thread, 也就是说getCurrentSession不会从spring context中去寻找current session, 而是会到org.hibernate.context.ThreadLocalSessionContext
这个上下文中去寻找current session, 没有就自动创建一个;这个时候, current session是在 org.hibernate.context.ThreadLocalSessionContext 上下文中创建的, 没有绑定通过Spring 声明式事务@Transactional 创建的 transaction, 因此, spring 就会报如下错误:
[java] view
plain copy
org.hibernate.HibernateException: save is not valid without active transaction org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:341)at com.sun.proxy.$Proxy12.save(Unknown Source)at cn.javass.h4.hello.UserDao.save(UserDao.java:18)
因为Hibernate的数据库操作是一定要在一个事务中进行的(参考Hibernate教程), 所以报了以上错误, 解决的办法很简单, 就是在调用getCurrentSessioin()后, 手动添加 session.beginTransaction() 和 transaction.commit() 语句将数据库操作包装进事务中。这种情况下, spring声明式事务就不起作用了, 只能使用编程式事务了。
hibernate.current_session_context_class主要就是thread和jta 两个取值。
先看一段话:
[html] view
plain copy
What does sessionFactory.getCurrentSession() do? First, you can call it
as many times and anywhere you
like, once you get hold of your SessionFactory (easy thanks to
HibernateUtil). The getCurrentSession()
method always returns the "current" unit of work. Remember that we
switched the configuration option for this
mechanism to "thread" in hibernate.cfg.xml? Hence, the scope of the
current unit of work is the current Java
thread that executes our application. However, this is not the full
truth. A Session begins when it is first
needed, when the first call to getCurrentSession() is made. It is then
bound by Hibernate to the current
thread. When the transaction ends, either committed or rolled back,
Hibernate also unbinds the Session from
the thread and closes it for you. If you call getCurrentSession() again,
you get a new Session and can start a
new unit of work. This thread-bound programming model is the most
popular way of using Hibernate.
再看下面一段(来自Hibernate官网)
[html] view
plain copy
The easiest way to handle Sessions and transactions is Hibernate's automatic "current" Session management.
For a discussion of contextual sessions see 第 2.3 节 “上下文相关的会话(Contextual Session)”.
Using the "jta" session context, if there is no Hibernate Session associated with the current
JTA transaction, one will be started and associated with that JTA transaction the first time you call sessionFactory.getCurrentSession().
The Sessions retrieved via getCurrentSession() in the "jta" context are set
to automatically flush before the transaction completes, close after the transaction completes,
and aggressively release JDBC connections after each statement.
This allows the Sessions to be managed by the life cycle of the JTA transaction to which it is associated,
keeping user code clean of such management concerns.
Your code can either use JTA programmatically thr
11449
ough UserTransaction,
or (recommended for portable code) use the Hibernate Transaction API to set transaction boundaries.
If you run in an EJB container, declarative transaction demarcation with CMT is preferred.
[html] view
plain copy
使用getCurrentSession的代码举例:
[java] view
plain copy
SessionFactory sf = new Configuration().configure()
.buildSessionFactory();
Session s = null;
Transaction t = null;
try {
// 准备数据
UserModel um = new UserModel();
um.setUuid(9);
um.setUserId("id1");
um.setName("name1");
um.setAge(1);
s = sf.getCurrentSession();
t = s.beginTransaction();
s.save(um);
t.commit();
} catch (Exception err) {
err.printStackTrace();
t.rollback();
} finally {
}
1. 这两个值的相同点
对于sessionFactory.getCurrentSession()操作而言, 这两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作每次请求一个session。Hibernate
session的起始和终结由数据库事务的生存来控制。也就是说, 对于thread而言, 当执行getCurrentSession时, session创建并绑定到当前线程,当事务提交时, session就关闭了, 无须手动关闭session (openSession方法需要手动关闭session); jta与此类似,当执行getCurrentSession时, session创建并绑定到当前JTA context, 当事务提交时, session就关闭了, 无须手动关闭session 。
2. 不同点
org.hibernate.context.JTASessionContext - 当前session根据JTA上下文来跟踪和界定(即保存在JTA上下文中)。这和以前的仅支持JTA的方法是完全一样的。
org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线程来跟踪和界定(即保存在当前线程上下文的threadlocal变量中)。
在JDBC的独立应用程序中(非容器集成环境下),取值只能是thread, 否则程序会报以下错误:
[java] view
plain copy
org.hibernate.HibernateException: No TransactionManagerLookup specified
at org.hibernate.context.JTASessionContext.currentSession(JTASessionContext.java:81)
at org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:687)
at com.cvv.service.UserManager.exists(UserManager.java:16)
在J2EE容器的环境下, 可以使用thread, 也可以使用jta, 因为容器环境中一般会配置 TransactionManagerLookup。并且,如果没有配置 hibernate.current_session_context_class,但是有org.hibernate.transaction.TransactionManagerLookup的配置的情况下,Hibernate会采用org.hibernate.context.JTASessionContext,即jta。容器环境优先考虑jta方式。
在Spring环境中,
除了thread和jta两个值以外, Spring 增加了 org.springframework.orm.hibernate4.SpringSessionContext 这个值。
1. 当你使用Spring 声明式事务的时候 (@Transactional, tx标签 ...), @Transactional声明式事务管理 会创建一个 绑定了事务的session并把 该session放到SpringSessionContext 这个上下文中, 所以在使用声明式事务并且使用 getCurrentSession()这个方法的时候,只有从 SpringSessionContext
上下文中才能取到当前的session, 这就要求将 hibernate.current_session_context_class 这个值设置为org.springframework.orm.hibernate4.SpringSessionContext, 在spring 配置文件中, 在使用LocalSessionFactoryBean时会自动的设置这个值,
不需要你去设置, 所以在spring 配置中 hibernate.current_session_context_class 默认就是SpringSessionContext;
2. 如果你将 hibernate.current_session_context_class 设置成了 thread,并不是不可以, 而是代码需要做些修改:
因为使用Spring 声明式事务的时候, 绑定了事务的session被放置在了spring context中,而当前hibernate.current_session_context_class值为 thread, 也就是说getCurrentSession不会从spring context中去寻找current session, 而是会到org.hibernate.context.ThreadLocalSessionContext
这个上下文中去寻找current session, 没有就自动创建一个;这个时候, current session是在 org.hibernate.context.ThreadLocalSessionContext 上下文中创建的, 没有绑定通过Spring 声明式事务@Transactional 创建的 transaction, 因此, spring 就会报如下错误:
[java] view
plain copy
org.hibernate.HibernateException: save is not valid without active transaction org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:341)at com.sun.proxy.$Proxy12.save(Unknown Source)at cn.javass.h4.hello.UserDao.save(UserDao.java:18)
因为Hibernate的数据库操作是一定要在一个事务中进行的(参考Hibernate教程), 所以报了以上错误, 解决的办法很简单, 就是在调用getCurrentSessioin()后, 手动添加 session.beginTransaction() 和 transaction.commit() 语句将数据库操作包装进事务中。这种情况下, spring声明式事务就不起作用了, 只能使用编程式事务了。
相关文章推荐
- java高仿百度贴吧九宫格验证码代码下载
- java学习顺序
- 关于Java 工程读取xml文件 运行 伪属性名的错误
- Java中equals和==
- Homework-IO
- 相册管理系统(Java表单+xml数据库存储)
- Java集合系列一:集合概述
- Java之CountDownLatch使用(转)
- Java动态编译
- Javah生成JNI文件
- Spring data jpa配置出错
- java NIO实现同步非阻塞服务器
- Hadoop:Java API实现
- spring+quartz实现定时任务(每天零点删除指定文件夹中缓存文件)
- SpringMVC 的第一个程序——HelloWorld
- Java自动内存管理机制(一) JVM、Class
- Jetty NIO模型
- Java 测试,按字节数截取字符串,不能输出半个中文
- 研读代码必须掌握的Eclipse快捷键
- 关于eclipse中同步代码报错checkout conflict with files的解决方法