`

Hibernate中对Session管理

    博客分类:
  • java
阅读更多
作者Blog:http://blog.csdn.net/jhxck/
各种Session 管理方案中, ThreadLocal 模式得到了大量使用。ThreadLocal 是Java中一种较为特殊的线程绑定机制。通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种隔离机制。首先,我们需要知道,SessionFactory负责创建Session,SessionFactory是线程
安全的,多个并发线程可以同时访问一个SessionFactory 并从中获取Session 实例。而
Session并非线程安全,也就是说,如果多个线程同时使用一个Session实例进行数据存取,
则将会导致Session 数据存取逻辑混乱。下面是一个典型的Servlet,我们试图通过一个类
变量session实现Session的重用,以避免每次操作都要重新创建:
public class TestServlet extends HttpServlet {
private Session session;
public void doGet( HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
session = getSession();
doSomething();
session.flush();
}
public void doSomething(){
......//基于session的存取操作
}
}
代码看上去正确无误,甚至在我们单机测试的时候可能也不会发生什么问题,但这样的代
Hibernate Developer's Guide Version 1.0
September 2, 2004 So many open source projects. Why not Open your Documents?
码一旦编译部署到实际运行环境中,接踵而来的莫名其妙的错误很可能会使得我们摸不找头脑。
问题出在哪里?
首先,Servlet 运行是多线程的,而应用服务器并不会为每个线程都创建一个Servlet
实例,也就是说,TestServlet在应用服务器中只有一个实例(在Tomcat中是这样,其他的
应用服务器可能有不同的实现),而这个实例会被许多个线程并发调用,doGet 方法也将被不
同的线程反复调用,可想而知,每次调用doGet 方法,这个唯一的TestServlet 实例的
session 变量都会被重置,线程A 的运行过程中,其他的线程如果也被执行,那么session
的引用将发生改变,之后线程A 再调用session,可能此时的session 与其之前所用的
session就不再一致,显然,错误也就不期而至。
ThreadLocal的出现,使得这个问题迎刃而解。
我们对上面的例子进行一些小小的修改:
public class TestServlet extends HttpServlet {
private ThreadLocal localSession = new ThreadLocal();
public void doGet( HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
localSession.set(getSession());
doSomething();
session.flush();
}
public void doSomething(){
Session session = (Session)localSession.get();
......//基于session的存取操作
}
}
可以看到,localSession 是一个ThreadLocal 类型的对象,在doGet 方法中,我们
通过其set 方法将获取的session 实例保存,而在doSomething 方法中,通过get 方法取
出session实例。
这也就是ThreadLocal的独特之处,它会为每个线程维护一个私有的变量空间。实际上,
其实现原理是在JVM 中维护一个Map,这个Map的key 就是当前的线程对象,而value则是
线程通过ThreadLocal.set方法保存的对象实例。当线程调用ThreadLocal.get方法时,
ThreadLocal会根据当前线程对象的引用,取出Map中对应的对象返回。
这样,ThreadLocal通过以各个线程对象的引用作为区分,从而将不同线程的变量隔离开
来。

Hibernate官方开发手册的示例中,提供了一个通过ThreadLocal维护Session的好
榜样:

public class HibernateUtil {
private static SessionFactory sessionFactory;
static {
try {
// Create the SessionFactory
sessionFactory = new
Configuration().configure().buildSessionFactory();
} catch (HibernateException ex) {
throw new RuntimeException(
"Configuration problem: " + ex.getMessage(),
ex
);
}
}
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException
{
Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet
if (s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
在代码中,只要借助上面这个工具类获取Session 实例,我们就可以实现线程范围内的
Session 共享,从而避免了在线程中频繁的创建和销毁Session 实例。不过注意在线程结束
时关闭Session。

同时值得一提的是,新版本的Hibernate在处理Session的时候已经内置了延迟加载机
制,只有在真正发生数据库操作的时候,才会从数据库连接池获取数据库连接,我们不必过于担
心Session的共享会导致整个线程生命周期内数据库连接被持续占用。



对于Web程序
而言,我们可以借助Servlet2.3规范中新引入的Filter机制,轻松实现线程生命周期内的
Session管理(关于Filter的具体描述,请参考Servlet2.3规范)。
Filter的生命周期贯穿了其所覆盖的Servlet(JSP也可以看作是一种特殊的Servlet)
及其底层对象。Filter在Servlet被调用之前执行,在Servlet调用结束之后结束。因此,
在Filter 中管理Session 对于Web 程序而言就显得水到渠成。下面是一个通过Filter 进
行Session管理的典型案例:
public class PersistenceFilter implements Filter
{
protected static ThreadLocal hibernateHolder = new ThreadLocal();
public void doFilter(ServletRequest request, ServletResponse
response, FilterChain chain)
throws IOException, ServletException
{
hibernateHolder.set(getSession());
try
{
......
chain.doFilter(request, response);
......
}
finally
{
Session sess = (Session)hibernateHolder.get();
if (sess != null)
{
hibernateHolder.set(null);
try
{
sess.close();
}
catch (HibernateException ex) {
throw new ServletException(ex);
}
}
}
}
......
Hibernate Developer's Guide Version 1.0
September 2, 2004 So many open source projects. Why not Open your Documents?
}
通过在doFilter中获取和关闭Session,并在周期内运行的所有对象(Filter链中其
余的Filter,及其覆盖的Servlet 和其他对象)对此Session 实例进行重用,保证了一个
Http Request处理过程中只占用一个Session,提高了整体性能表现。
在实际设计中,Session的重用做到线程级别一般已经足够,企图通过HttpSession实
现用户级的Session重用反而可能导致其他的问题。凡事不能过火,Session重用也一样。

作者Blog:http://blog.csdn.net/jhxck/
分享到:
评论

相关推荐

    Hibernate-nosession

    本文将深入探讨Hibernate-nosession的概念、应用场景以及如何在实际代码中实现。 首先,理解什么是Hibernate Session。Session是Hibernate中的核心接口,它充当了应用程序和数据库之间的桥梁,负责对象的持久化操作...

    hibernate中session的管理

    在实际开发中,除了使用ThreadLocal,还有其他几种Session管理策略,例如: 1. **Session per Request/Transaction**:每个HTTP请求或数据库事务分配一个Session。这通常是Web应用程序的最佳实践,因为HTTP请求是...

    Hibernate(session管理)

    本文将深入探讨Hibernate中的核心概念——Session管理。 首先,理解Session在Hibernate中的角色至关重要。Session是Hibernate的主要工作单元,它是应用程序与数据库之间的桥梁。它负责保存、检索和更新Java对象,...

    Hibernate Session释放模式

    这是最常见的Session管理方式,通常与Spring的@Transactional注解结合使用。每个数据库事务开始时创建Session,事务结束时关闭Session。这种方式简单且易于理解,能保证事务的ACID特性,但可能会导致大量的短连接,...

    Hibernate_Session_Transaction

    在Java的持久化框架Hibernate中,`Session`和`Transaction`是两个至关重要的概念,它们在数据管理和事务处理中起到核心作用。这篇文章将深入解析这两个概念及其相关知识点。 `Session`是Hibernate提供的一种与...

    重写hibernate的session简单增删改查

    在实际开发中,为了满足特定需求,有时我们需要对Hibernate的默认Session行为进行扩展或覆盖。例如,可能需要添加日志记录、事务控制、性能优化等功能。这就需要我们创建一个自定义的Session工厂(SessionFactory)...

    hibernate和session学习

    通过Hibernate,我们可以将数据库中的表与Java类进行映射,从而实现对数据库的操作,而无需编写大量的SQL语句。这极大地提高了开发效率,降低了代码的复杂性。 在Hibernate中,`SessionFactory`是核心组件之一,它...

    实现自己的Hibernate框架之Session 方法实现

    在IT行业中,数据库操作是应用程序开发中的重要环节,而Hibernate作为一个强大的对象关系映射(ORM)框架,极大地简化了Java应用程序对数据库的操作。本篇文章将深入探讨如何实现自己的Hibernate框架,特别是Session...

    Hibernate_11session

    通过以上介绍,我们可以看到Hibernate Session在数据库操作中的核心地位,正确理解和使用Session是掌握Hibernate的关键。实践中的具体应用需要结合项目需求,灵活运用这些知识,以实现高效、稳定的数据库访问。

    hibernate session生命周期示例

    通过合理的Session管理,我们可以减少数据库交互的复杂性,提高程序性能,并避免数据一致性问题。实践中,还要注意避免频繁打开和关闭Session,以及合理控制事务的粒度,以达到最佳的性能效果。

    Hibernate的Session的javadoc

    Hibernate的Session接口是Java应用程序与Hibernate之间主要的运行时交互接口,它提供了对持久化对象的创建、读取和删除操作。Session的概念是基于对象的状态管理和数据库事务的,它的生命周期通常与一个物理事务绑定...

    hibernate02:session对象、hql查询、在线查询也叫对象查询、离线查询

    在Hibernate中,`Session`是应用程序与数据库之间的桥梁,它是ORM(Object-Relational Mapping)的主要工作接口。`Session`提供了在数据库中保存、更新和删除对象的方法,同时也负责加载或检索对象。它具有事务管理...

    hibernate的session.flush

    总结来说,`Session.flush()`是Hibernate中不可或缺的一部分,它确保了数据库与应用程序的同步,同时也涉及到了缓存管理、事务控制等多个重要概念。开发者在使用Hibernate时,应当合理运用`flush()`,以提高应用的...

    Hibernate中获取Session的两种方式代码示例

    Hibernate中获取Session的两种方式代码示例 Hibernate 是一个流行的基于Java的持久层框架,提供了对数据库的访问和操作。Session 是 Hibernate 中一个核心概念,负责管理应用程序与数据库之间的交互。获取 Session ...

    hibernate--3.Hibernate数据持久化(通过 Session 操纵对象)

    首先,我们需要理解Session在Hibernate中的角色。Session是Hibernate的核心接口之一,它负责对象的持久化操作,比如保存、更新、删除和检索对象。Session对象就像一个临时的工作区域,用于在应用程序和数据库之间...

    对Hibernate Session做一个简单的包装

    然而,在实际开发中,我们往往需要根据项目需求对其进行定制,例如添加事务管理、异常处理、日志记录等功能,这就涉及到了对`Session`的封装。 在提供的`HibernateSessionWrapper.java`文件中,我们可以预期它实现...

    Spring与Hibernate集成中的session

    本文将详细探讨Spring与Hibernate的集成,特别是如何在集成环境中使用和管理`Session`。 首先,Spring作为一个轻量级的框架,提供了强大的依赖注入(DI)和面向切面编程(AOP)功能,它可以帮助我们解耦应用程序...

    JAVA的hibernate手动获取session的方法

    本篇将详细讲解如何在Hibernate中手动获取Session,以及涉及到的相关配置和连接管理。 首先,理解Hibernate的核心组件——Session。Session是Hibernate中的工作单元,它是与数据库交互的主要接口,负责保存、更新和...

    day36 11-Hibernate中的事务:当前线程中的session

    本文将深入探讨Hibernate中的事务处理,特别是“当前线程中的Session”这一概念,以及如何在实际开发中有效地利用它。 在Hibernate中,Session是与持久化层交互的主要接口,它负责对象的持久化、检索、更新和删除等...

    hibernate的核心接口--Session

    - **定义**: Session 是 Hibernate 框架中最常用的接口之一,它又被称为持久化管理器。Session 负责所有与数据库交互的工作,包括管理持久化对象的生命周期,并通过提供第一级别的高级缓存来确保持久化对象的数据与...

Global site tag (gtag.js) - Google Analytics