`
newleague
  • 浏览: 1499522 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

数据库持久层——浅谈hibernate中的Session

 
阅读更多

大多数情况下,Session 管理的目标聚焦于通过合理的设计,避免Session 的频繁创建

和销毁,从而避免大量的内存开销和频繁的JVM垃圾回收,保证系统高效平滑运行。

在各种Session 管理方案中, ThreadLocal 模式得到了大量使用。ThreadLocal 

Java中一种较为特殊的线程绑定机制。通过ThreadLocal存取的数据,总是与当前线程相关,

也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种隔离机制。

首先,我们需要知道,SessionFactory负责创建SessionSessionFactory是线程

安全的,多个并发线程可以同时访问一个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的存取操作

}

}

代码看上去正确无误,甚至在我们单机测试的时候可能也不会发生什么问题,但这样的代

码一旦编译部署到实际运行环境中,接踵而来的莫名其妙的错误很可能会使得我们摸不找头脑。

问题出在哪里?

首先,Servlet 运行是多线程的,而应用服务器并不会为每个线程都创建一个Servlet

实例,也就是说,TestServlet在应用服务器中只有一个实例(在Tomcat中是这样,其他的

应用服务器可能有不同的实现),而这个实例会被许多个线程并发调用,doGet 方法也将被不

同的线程反复调用,可想而知,每次调用doGet 方法,这个唯一的TestServlet 实例的

session 变量都会被重置,线程的运行过程中,其他的线程如果也被执行,那么session

的引用将发生改变,之后线程再调用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,这个Mapkey 就是当前的线程对象,而value则是

线程通过ThreadLocal.set方法保存的对象实例。当线程调用ThreadLocal.get方法时,

ThreadLocal会根据当前线程对象的引用,取出Map中对应的对象返回。

这样,ThreadLocal通过以各个线程对象的引用作为区分,从而将不同线程的变量隔离开

来。

回到上面的例子,通过应用ThreadLocal 机制,线程session 实例只能为线程A

所用,同样,其他线程的session实例也各自从属于自己的线程。这样,我们就实现了线程安

全的Session共享机制。

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

榜样:

public class HibernateUtil {

private static final 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的共享会导致整个线程生命周期内数据库连接被持续占用。

上面的HibernateUtil类可以应用在任何类型的Java程序中。特别的,对于Web程序

而言,我们可以借助Servlet2.3规范中新引入的Filter机制,轻松实现线程生命周期内的

Session管理(关于Filter的具体描述,请参考Servlet2.3规范)。

Filter的生命周期贯穿了其所覆盖的ServletJSP也可以看作是一种特殊的Servlet

及其底层对象。FilterServlet被调用之前执行,在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);

}

}

}

}

……

}

通过在doFilter中获取和关闭Session,并在周期内运行的所有对象(Filter链中其

余的Filter,及其覆盖的Servlet 和其他对象)对此Session 实例进行重用,保证了一个

Http Request处理过程中只占用一个Session,提高了整体性能表现。

在实际设计中,Session的重用做到线程级别一般已经足够,企图通过HttpSession

现用户级的Session重用反而可能导致其他的问题。凡事不能过火,Session重用也一样。

分享到:
评论

相关推荐

    精通hibernate3.0--java数据库持久层开发实践(付京周)2

    根据提供的文件信息,“精通Hibernate3.0—Java数据库持久层开发实践(付京周)”这一书籍主要聚焦于使用Hibernate框架进行Java应用的数据库持久层开发。本书旨在帮助读者深入理解并掌握Hibernate的核心概念和技术...

    精通hibernate3.0--java数据库持久层开发实践(付京周)

    精通hibernate3.0--java数据库持久层开发实践(付京周) 分两卷下载,需要积分共1分。谢谢 精通hibernate3.0--java数据库持久层开发实践(付京周) 分两卷下载,需要积分共1分。谢谢

    HIBERNATE+-+符合Java习惯的关系数据库持久化.pdf

    HIBERNATE+-+符合Java习惯的关系数据库持久化

    钢炮级 持久层 —— 中篇

    标题 "钢炮级 持久层 —— 中篇" 提到的是关于持久层技术的深入探讨,这通常指的是在软件开发中用于处理数据库交互的框架或库。持久层是应用程序与数据库之间的桥梁,它负责数据的存储和检索,使得业务逻辑与数据...

    EJB+JPA数据库持久层开发实践详解

    EJB+JPA数据库持久层开发实践详解.pdf 完整版

    Hibernate-nosession

    Session是Hibernate中的核心接口,它充当了应用程序和数据库之间的桥梁,负责对象的持久化操作,如保存、更新、删除和查询等。Session通常在一个事务中打开并在事务结束时关闭,以确保数据的一致性和完整性。 然而...

    Hibernate执行持久层访问步骤

    《Hibernate执行持久层访问步骤详解...以上就是Hibernate执行持久层访问的基本步骤,掌握这些知识点,能帮助开发者高效地进行数据库操作。在实际开发中,还需要结合具体业务需求灵活运用,不断优化代码,提升系统性能。

    深入浅出 Hibernate.pdf

    具体来说,当一个Java对象被持久化到数据库时,Hibernate会自动执行必要的SQL语句来插入或更新数据库中的记录;当从数据库加载对象时,Hibernate则会根据查询结果构建相应的Java对象实例。 ### Hibernate的优势 1....

    重写hibernate的session简单增删改查

    在Java的持久化框架中,Hibernate是一个非常流行的ORM(对象关系映射)工具,它使得开发者可以使用面向对象的方式来操作数据库。"重写hibernate的session简单增删改查"是一个针对初学者的实践教程,旨在帮助理解如何...

    HIBERNATE - 符合Java习惯的关系数据库持久化.htm

    HIBERNATE - 符合Java习惯的关系数据库持久化.htm

    JSP源码——Struts+Hibernate实现MVC_strutsmvc.zip

    2. **DAO(Data Access Object)模式**:在业务层与持久层之间创建一个抽象层,用于执行数据库操作,方便Struts与Hibernate的交互。 3. **模型驱动**:Struts2支持模型驱动的方式,可以直接使用Hibernate的实体对象...

    深入浅出Hibernate中文版 part1

    8.2 根据数据库定义生成映射文件——MiddleGen 8.3 Hibernate官方工具 8.4 XDoclet-同步Hibernate基础代码 8.5 工具的使用周期 第9章 Hibernate XDoclet模板配置 9.1 IDEA 9.2 Eclipse 第10章 Hibernate益友...

    Hibernate(session管理)

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

    DSDAO数据库持久层

    即支持对象式的操作也支持SQL操作,整个持久层的使用除了需要配置数据库连接外,无需其它配置,使用上比HIBERNATE/MYBIATIS更简单,而功能与这些知名的数据库持久层相近。

    hibernate和session学习

    在实际应用中,我们通常会将`SessionFactory`和`Session`的管理封装到DAO(Data Access Object)层,以便于业务逻辑层调用。同时,为了优化性能,Hibernate还提供了二级缓存,可以通过配置将频繁访问的数据存储在...

    Hibernate_Session_Transaction

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

    junit学习(十)——Springpring与Hibernate整合的单元测试

    在本篇《junit学习(十)——Spring与Hibernate整合的单元测试》中,我们将探讨如何在Java开发中,利用JUnit进行Spring和Hibernate框架的集成测试。单元测试是软件开发中的重要环节,它能帮助开发者确保代码的质量和...

    Hibernate 符合JAVA习惯的关系数据库持久化.pdf

    **Hibernate:符合JAVA习惯的关系数据库持久化** Hibernate是一款强大的Java对象关系映射(ORM)框架,它极大地简化了Java应用程序与关系数据库之间的交互。通过提供一套API和元数据描述,Hibernate能够将Java类与...

    Hibernate数据持久层框架v5.2.13

    Hibernate也是目前Java开发中最为流行的数据库持久层框架,现已归JBOSS所有。 它的设计目标是将软件开发人员从大量相同的数据持久层相关编程工作中解放出来。无论是从设计草案还是从一个遗留数据库开

    Hibernate 基于持久层框架的DAO模式应用

    在基于持久层框架的DAO(Data Access Object)模式应用中,Hibernate扮演着核心角色,使得业务逻辑和数据访问逻辑分离,提高了代码的可复用性和可维护性。 1. **DAO模式的理解** DAO模式是一种设计模式,它创建了...

Global site tag (gtag.js) - Google Analytics