新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论Java, J2SE, J2ME, J2EE, 以及Eclipse, NetBeans, JBuilder等Java开发环境,还有JSP, JavaServlet, JavaBean, EJB以及struts, hibernate, spring, webwork2, Java 3D, JOGL等相关技术。
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Java/Eclipse 』 → Hibernate中对Session管理 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 6921 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: Hibernate中对Session管理 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     npuhetao 帅哥哟,离线,有人找我吗?
      
      
      威望:5
      头衔:骨灰级菜鸟
      等级:大二(研究C++)
      文章:230
      积分:2708
      门派:XML.ORG.CN
      注册:2004/3/18

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给npuhetao发送一个短消息 把npuhetao加入好友 查看npuhetao的个人资料 搜索npuhetao在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看npuhetao的博客楼主
    发贴心情 Hibernate中对Session管理

    在各种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重用也一样。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    你硬要把单纯的事情看得很严重,那样子你会很痛苦。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/3/14 13:43:00
     
     yule 帅哥哟,离线,有人找我吗?
      
      
      等级:大一新生
      文章:3
      积分:66
      门派:XML.ORG.CN
      注册:2005/8/8

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给yule发送一个短消息 把yule加入好友 查看yule的个人资料 搜索yule在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看yule的博客2
    发贴心情 
    顶一个
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/8/8 10:21:00
     
     binaryluo 帅哥哟,离线,有人找我吗?
      
      
      威望:6
      等级:研二(Pi-Calculus看得一头雾水)(版主)
      文章:679
      积分:5543
      门派:IEEE.ORG.CN
      注册:2005/2/19

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给binaryluo发送一个短消息 把binaryluo加入好友 查看binaryluo的个人资料 搜索binaryluo在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看binaryluo的博客3
    发贴心情 
    up
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/8/10 9:59:00
     
     kingbillow 帅哥哟,离线,有人找我吗?
      
      
      等级:大二(研究汇编)
      文章:45
      积分:252
      门派:XML.ORG.CN
      注册:2004/9/24

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给kingbillow发送一个短消息 把kingbillow加入好友 查看kingbillow的个人资料 搜索kingbillow在『 Java/Eclipse 』的所有贴子 引用回复这个贴子 回复这个贴子 查看kingbillow的博客4
    发贴心情 
    支持一下可以
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/8/25 17:01:00
     
     lywzd 帅哥哟,离线,有人找我吗?
      
      
      等级:大二期末(C++考了100分!)
      文章:69
      积分:324
      门派:XML.ORG.CN
      注册:2005/10/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给lywzd发送一个短消息 把lywzd加入好友 查看lywzd的个人资料 搜索lywzd在『 Java/Eclipse 』的所有贴子 点击这里发送电邮给lywzd 引用回复这个贴子 回复这个贴子 查看lywzd的博客5
    发贴心情 
    不过这样做的一个很麻烦的问题就是SESSION的关闭问题,我应该什么时候关掉它,如果做一次数据库操作关一次的话,那就没有必要共享了,但是,若不这样,又能怎样呢?它具体用到什么地方????
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/11/2 16:17:00
     
     lywzd 帅哥哟,离线,有人找我吗?
      
      
      等级:大二期末(C++考了100分!)
      文章:69
      积分:324
      门派:XML.ORG.CN
      注册:2005/10/31

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给lywzd发送一个短消息 把lywzd加入好友 查看lywzd的个人资料 搜索lywzd在『 Java/Eclipse 』的所有贴子 点击这里发送电邮给lywzd 引用回复这个贴子 回复这个贴子 查看lywzd的博客6
    发贴心情 
    希望能够给指点一下
    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2005/11/2 16:18:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Java/Eclipse 』的所有贴子 点击这里发送电邮给Google AdSense 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/12 3:10:36

    本主题贴数6,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    93.750ms