无论是立即加载还是延迟加载必须要连接数据库的,而在java中连接数据库是依赖java.sql.Connection,在hibernate中session就是Connection的一层高级封装,一个session对应了一个Connection,要实现延迟加载必须有session才行.而且要进行延迟加载还必须保证是同一个session才行,用另外一个session去延迟加载前一个session的代理对象是不行的.大家都知道Connection是使用过后必须要进行关闭的,那么我们如何保证一次http请求过程中,一直都使用一个session呢,即一个Connection呢.而且还要保证http请求结束后正确的关闭.
好,现在我们知道了我们要解决的问题
1.如何保证http请求结束后正确的关闭session
2.如何保证http请求过程中一直使用同一个session
第一个问题很容易想到,使用过滤器
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) {
try {
filterChain.doFilter(request, response);
} catch (IOException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
} finally {
try {
HibernateUtil.commitTransaction();
} catch (Exception e) {
HibernateUtil.rollbackTransaction();
} finally {
HibernateUtil.closeSession();
}
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) {
try {
filterChain.doFilter(request, response);
} catch (IOException e) {
e.printStackTrace();
} catch (ServletException e) {
e.printStackTrace();
} finally {
try {
HibernateUtil.commitTransaction();
} catch (Exception e) {
HibernateUtil.rollbackTransaction();
} finally {
HibernateUtil.closeSession();
}
}
}
要解决第二个问题我们必须先搞清楚,http请求在java中是以什么样的机制实现的,在java中一个请求就是一个线程,像流行的web容器Tomcat等,往往都是采用线程池机制的也就是说有n个线程在池子里面,每当有http请求时,随机从线程池中取出一个线程对象去处理请求,实际上多次请求可能使用的是同一线程也可能不是,这是随机的.要保证整个请求中使用同一session最容易想到的就是把这个session绑定到线程上,在java中使用ThreadLocal可以轻松绑定变量,每个线程有一个自己的ThreadLocal,这个ThreadLocal会随线程的销毁一起销毁,既然是每个线程有一个那么多个线程间自然是不会有影响了,所以把session绑定在ThreadLocal里面是最好的选择了,
有关ThreadLocal的更多资料,大家可以百度或者参考
http://www-128.ibm.com/developerworks/cn/java/j-threads/index3.html
http://www.blogjava.net/jspark/archive/2006/08/01/61165.html
最后我把相关的代码发出来
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import java.sql.Connection;
import org.apache.log4j.Logger;
import java.io.File;
/**
*
* <p>
* Title:Hibernate工具类
* </p>
*
* <p>
* 利用ThreadLocal 绑定 Hibernate 的session
* </p>
*
* @author 孙钰佳
* @mail sunyujia@yahoo.cn
* @version 1.0
*/
public class HibernateUtil {
/**
* Loger4j的logger
*/
private static final Logger logger = Logger.getLogger(HibernateUtil.class);
/**
* 存储hibernate session的ThreadLocal
*/
private static final ThreadLocal sessionThread = new ThreadLocal();
/**
* 存储事务的ThreadLocal
*/
private static final ThreadLocal transactionThread = new ThreadLocal();
/**
* Hibernate 的 Session工厂
*/
private static SessionFactory sessionFactory = null;
/**
* 初始化SessionFactory
*
* @param file
* Hibernate配置文件
*/
public static void initSessionFactory(File file) {
Configuration config = new Configuration();
config.configure(file);
sessionFactory = config.buildSessionFactory();
}
/**
* 获取当前线程绑定的session
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() {
Session s = (Session) sessionThread.get();
if (s == null) {
s = sessionFactory.openSession();
sessionThread.set(s);
} else {
Connection conn = s.connection();
try {
if (conn == null || conn.isClosed()) {
try {
s.close();
} catch (HibernateException e) {
logger.warn("close session error:" + e.getMessage(), e);
}
s = sessionFactory.openSession();
sessionThread.set(s);
}
} catch (SQLException e) {
throw new HibernateException(e);
}
}
return s;
}
/**
* 取得当前session的事务
*
* @return Transaction
*/
public static Transaction transaction() {
Transaction transaction = (Transaction) transactionThread.get();
if (transaction == null) {
transaction = getSession().beginTransaction();
transactionThread.set(transaction);
}
return transaction;
}
/**
* 提交当前session的事务
*/
public static void commitTransaction() {
Transaction transaction = (Transaction) transactionThread.get();
transactionThread.set(null);
if (transaction != null)
transaction.commit();
}
/**
* 回滚当前session的事务
*/
public static void rollbackTransaction() {
Transaction tx = (Transaction) transactionThread.get();
transactionThread.set(null);
if (tx != null)
tx.rollback();
}
/**
* 关闭当前线程使用的session
*/
public static void closeSession() {
Session session = (Session) sessionThread.get();
if (session != null) {
session.clear();
session.close();
sessionThread.set(null);
}
}
}
下面是一个调用的例子:
public static void main(String[] args) throws Exception {
HibernateUtil.initSessionFactory(new File(Test.class.getClassLoader()
.getResource("hibernate.cfg.xml").getFile()));
Session session = HibernateUtil.getSession();
HibernateUtil.transaction();
User u = new User();
u.setName("test");
session.save(u);
HibernateUtil.commitTransaction();
HibernateUtil.closeSession();
}
分享到:
相关推荐
本篇文章将详细探讨Hibernate中Session的管理,特别是如何利用ThreadLocal解决并发问题。 首先,SessionFactory是Hibernate的核心组件,它是一个线程安全的工厂类,用于创建Session实例。SessionFactory通常在应用...
描述虽然为空,但我们可以根据标题推测这篇博客可能讨论了如何在多线程环境下利用ThreadLocal来管理Hibernate的Session。在多线程应用中,每个请求通常对应一个独立的线程,而Session是数据库连接的一个会话,如果在...
Hibernate框架在处理数据库操作时,使用ThreadLocal来管理Session,确保每个线程都有自己独立的Session对象。这样,即使多个线程并发执行,每个线程也不会干扰其他线程的Session,避免了数据错乱的问题。例如,...
3. 存储数据库会话:在Spring Hibernate ORM中,ThreadLocal常用来保存数据库连接的Session,确保每个线程有自己的Session,避免线程间的资源冲突。 总之,ThreadLocal是一个强大的工具,但理解其工作原理和潜在...
`HibernateSessionFactory` 使用ThreadLocal变量`threadLocal`来存储线程绑定的Session实例。ThreadLocal是一种线程局部变量,每个线程都有自己的副本,不会互相干扰。这确保了每个线程都有独立的Session实例,避免...
2. 绑定Session:拦截器需要在Action上下文中绑定Session,这样Action就可以在需要的时候获取到它。这通常通过`ThreadLocal`实现,使得每个线程都有自己的Session副本。 3. 懒加载处理:由于OSIV模式下Session保持...
本文将深入探讨Hibernate中的事务处理,特别是“当前线程中的Session”这一概念,以及如何在实际开发中有效地利用它。 在Hibernate中,Session是与持久化层交互的主要接口,它负责对象的持久化、检索、更新和删除等...
题目起的有些拗口了,简单说,这篇文章想要解释Spring为什么会选择使用ThreadLocal将资源和事务绑定到线程上,这背后有着什么样的起因和设计动机,通过分析帮助大家更清晰地认识Spring的线程绑定机制。访问任何带有...
在实际应用中,如上文所示的Hibernate示例,通过`set()`方法可以将`Session`对象与当前线程绑定,而`get()`方法则用于获取当前线程的`Session`对象。这种设计模式避免了在多线程环境中直接操作共享资源可能带来的...
ThreadLocal变量可以绑定到处理请求的线程,使得代码能方便地访问Session,而事务上下文环境也可存储在ThreadLocal中,根据所选的事务划分机制进行管理。这种方式被称为ThreadLocal Session和Open Session in View...
Hibernate 使用 `ThreadLocal` 来保持每个线程与 `Session` 的对应关系,确保线程安全。`getCurrentSession()` 方法能方便地获取当前线程关联的 `Session`。 11. **JDBC 步骤**: JDBC 连接数据库的基本步骤包括...
private static final ThreadLocal<Session> threadLocal = new ThreadLocal(); private static Configuration config = null; private static SessionFactory sessionFactory = null; static { try { config...
例如,Spring 中的 TransactionTemplate 和 AOP 模块利用 `ThreadLocal` 存储当前事务信息,Hibernate 中的 Session 管理也依赖于 `ThreadLocal` 来保持线程绑定的 Session。 7. **线程安全** - `ThreadLocal` ...
3. **Session**:Session 是 Hibernate 中实际执行数据库操作的接口,它代表一次数据库会话。`SessionFactory.openSession()` 创建一个新的 Session 实例,用于执行 CRUD(创建、读取、更新、删除)操作。 4. **...
Hibernate通过绑定Session到ThreadLocal来保证在同一个请求中使用的Session是一致的,即使在HTTP请求结束后,也能正确关闭Session。 **四、缓存查询流程** 当试图通过ID获取对象时,Hibernate会先查找一级缓存,...
例如,Hibernate框架中,使用ThreadLocal来存储每个线程的Session实例,这样每个线程都有自己的Session,避免了线程间的数据混乱。以下是一个简单的例子: ```java public static final ThreadLocal<Session> ...
为了实现这一功能,我们将采用Spring框架进行整体架构的设计与管理,并利用Hibernate作为持久层框架。Spring提供了强大的AOP支持以及灵活的配置机制,而Hibernate则具备出色的ORM映射能力,二者结合可以高效地实现...