`

Hibernate(21):getCurrentSession还是用openSession?

阅读更多

    从Hibernate(十九): 异常"Session was already closed" 开始的,连着几遍针对"Session was already closed"问题的持续跟踪, 在上篇Hibernate(20):默认情况下决定commit时session命运的 三个条件里最终找到了源头. 路途虽说艰辛,但收获还是不小, "拔萝卜带出泥"地引出了一系列Hibernate世界里的基本构架. 在接下来,我们先来看getCurrentSession与openSession有什么区别.
--------------------
    我们知道, 一般来说, 为了使用Session, 可以有两种方式: 调用SessionFactory的getCurrentSession或openSession. 那么这两个方法有什么不同? 使用时有什么注意点? 再往深地说, 这样的设计对于我们有什么借鉴之处?

    好像是Hibernate以前的版本里没有getCurrentSession方法, 它是后来新加的(文档中有这样的描述: Starting with version 3.0.1, Hibernate added the SessionFactory.getCurrentSession() method). 为什么要加呢? Hibernate自己的文档里有这方面的介绍, 这里就不copy/paste到这了. 总的一个核心思想就是想达到"Contextual Sessions"效果. 这个效果是通过一个接口 org.hibernate.context.CurrentSessionContext来实现的, 一般最常用的是它的实现类org.hibernate.context.ThreadLocalSessionContext. 对应的配置是,hibernate.cfg.xml文件中的<property name="current_session_context_class">thread</property>.

    配置是这样的, 那么具体在代码层面又是怎么实现的? 我们从SessionFactory的getCurrentSession方法说起,照应题目中的疑问,先看从getCurrentSession的实现来看其的好处.

    在这个方法中, 首先判断有没有配置currentSessionContext,如有的话,再调用currentSessionContext的currentSession方法. 那么这个currentSessionContext 是什么时候创建的? 
    在SessionFactory(实现类SessionFactoryImpl)的构造方法中, 我们找到一句: currentSessionContext = buildCurrentSessionContext();在buildCurrentSessionContext方法中, hibernate从配置文件中取出current_session_context_class信息, (此方法中有个transactionManager的问题, 这里先不讨论),据这个current_session_context_class是否为jta或thread或managed相应创建 Hibernate内置org.hibernate.context.CurrentSessionContext接口的实现类 JTASessionContext或ThreadLocalSessionContext或ManagedSessionContext. 另外,buildCurrentSessionContext方法还支持自定义的CurrentSessionContext接口实现,这里也不做介绍.

    这里我们直接进到ThreadLocalSessionContext实现类的currentSession方法,这个也就是SessionFactory的getCurrentSession最终要调用的方法.

    首先第一句是existingSession( factory ), 这个没啥可说的, 它是想从ThreadLocal里取出与传入的factory 相对应的Session. 如果没有,就调用buildOrObtainSession, 总觉得这个方法有些歧义,看它的实现发现实际上是new了一个Session,而没有什么Obtain, new一个session是通过SessionFactory的openSession(final Connection connection,
final boolean flushBeforeCompletionEnabled,final boolean autoCloseSessionEnabled,final ConnectionReleaseMode connectionReleaseMode)方法. 这里的autoCloseSessionEnabled也就是ThreadLocalSessionContext类里写死的 isAutoCloseEnabled方法,也就是它最终导致了t.commit()后session.close时,"Session was already closed"异常的抛出.

    再看current.getTransaction().registerSynchronization( buildCleanupSynch() )一句, 第一次见registerSynchronization方法, 它是干啥的? 要给跟刚才通过buildOrObtainSession方法新建的Session绑定一个 javax.transaction.Synchronization实现. 这里看到是绑定了一个unbind( factory )方法, 看样子是在事务结束后将ThreadLocal里绑定的session去除掉. (是不是也正是这个registerSynchronization方法, 才有了三个条件 中的callback为true了?日后再进一步观察验证 ).

    接下来是是否对新建session是否要做代理wrap的判断和相应处理.(这样也就解决了为什么debug跟踪时session.save方法时总先要 执行ThreadLocalSessionContext.TransactionProtectionWrapper类里invoke方法,一个新问 题: 从TransactionProtectionWrapper的名字看是要做"事务保护",那么这个事务保护又是怎么实现的?若不保护又怎样?这两个问题 先放着)

    再接下来就是通过执行doBind方法将新建的session绑定到ThreadLocal了.

    这篇中,引出问题后,从getCurrentSession的实现看到有如下好处:
        1, 如果ThreadLocal里已有,就不必再新建session,这样也就为session的方便获取做好的铺垫.
        2, 若新建session,对其对应的Transaction做了registerSynchronization,这里做了unbind( factory )处理.
        3, 若新建session,视情况再做代理封装,这里封装为TransactionProtectionWrapper.
    下一篇中, 我们将看openSession有什么优势?

7
3
分享到:
评论

相关推荐

    getCurrentSession 与 openSession() 的区别

    在Java的Hibernate框架中,`getCurrentSession()` 和 `openSession()` 都是用于获取与数据库交互的Session对象,但它们之间存在显著的区别。理解这些差异对于优化数据访问性能和管理事务至关重要。 首先,`...

    SessionFactory.getCurrentSession与openSession的区别

    标题中的“SessionFactory.getCurrentSession与openSession的区别”是关于Hibernate框架中的两个关键操作,它们都是用于在Hibernate中获取数据库会话的。理解它们的区别对于优化数据访问性能和管理事务至关重要。 ...

    新Hibernate SessionFactory().getCurrentSession()猫腻

    标题中的“新Hibernate SessionFactory().getCurrentSession()猫腻”指的是在使用Hibernate ORM框架时,一个常见但不为人熟知的细节,即SessionFactory().getCurrentSession()方法的使用。在深入讲解这个知识点之前...

    ssh中getCurrentSession的使用

    2. **为什么使用getCurrentSession()**:与直接调用`openSession()`创建新的Session相比,`getCurrentSession()`有以下优势: - 它能够自动管理Session的生命周期,比如在请求结束时关闭Session,避免资源泄露。 -...

    Hibernate存储Clob字段的方式总结

    同时,还探讨了Hibernate框架中getCurrentSession()与openSession()的区别。 首先,要操作数据库中的Clob字段,需要关注的是如何在Java对象与Clob字段之间进行转换。由于Clob字段通常用于存储大量文本数据,如果...

    hibernate.jar包

    - 获取Session:通过SessionFactory的openSession()或getCurrentSession()获取Session实例。 - 开启事务:在Session上开始一个新的数据库事务。 - 对象操作:执行增删改查操作,如save()、update()、delete()、...

    2020版Hibernate 12 道.pdf

    11. Hibernate中getCurrentSession和openSession的区别是什么? `getCurrentSession`是用于在已有的事务上下文中获取或创建Session,确保与当前事务的一致性。而`openSession`则是直接创建一个新的Session,不考虑...

    hibernate 学习笔记

    hibernate 学习笔记: 了解hibernate的基本概念 配置hbm.xml cfg.xml 快速入门案例3: 从domain-xml-数据库表 ...openSession()和getCurrentSession() 线程局部变量模式 transaction事务 在web项目中开发hibernate

    [尚硅谷]_佟刚_Hibernate面试题分析

    以上知识点覆盖了Hibernate的核心概念和操作,面试中涉及到这些内容时,应聘者应能清晰地表达对Hibernate框架的理解和使用经验,特别是在检索方式、对象状态管理、缓存机制以及性能优化方面的知识。此外,对 ...

    Hibernate的框架的总结

    本文详细介绍了Hibernate框架中的核心配置文件`hibernate.cfg.xml`及其配置项、映射文件`xxx.hbm.xml`,以及核心API如Configuration和SessionFactory的使用方法,并对C3P0连接池进行了简要说明。通过这些内容的学习...

    HIBERNATE4开发文档,HIBERNATE4的变化

    - 使用Spring管理Hibernate事务时,无论是注解方式还是XML配置方式,都应使用`HibernateTransactionManager`。示例如下: ```xml &lt;bean id="txManager" class="org.springframework.orm.hibernate4....

    hibernate学习教程

    - Session的获取:通过SessionFactory的openSession()或getCurrentSession()方法。 - CRUD操作:使用Session的save(), saveOrUpdate(), get(), update(), delete()等方法。 - 查询:使用Criteria API或HQL进行...

    hibernate 4.3.10 版本的笔记

    通过以上步骤和细节的介绍,我们对Hibernate 4.3.10版本有了较为全面的理解,包括环境搭建、实体映射、SessionFactory和Session的使用,以及生命周期状态的概念等。这对于开发者来说是非常宝贵的知识点,能够帮助...

    spring_hibernate_annotation的三种实现

    - 在实现类中,使用`SessionFactory`的`openSession()`方法获取`Session`,然后调用`Session`的方法执行CRUD操作,如`save()`, `get()`, `update()`, `delete()`等。 6. 示例代码: ```java @Repository public...

    hibernate学习笔记

    Hibernate是Java领域中一款流行的持久化框架,它实现了对象关系映射(O/R Mapping),将复杂的数据库操作转化为对Java对象的操作,从而简化了开发过程。本文主要围绕Hibernate 3.2的学习笔记,涵盖其基本概念、配置...

    hibernate登录页面测试

    本测试着重于使用Hibernate构建登录页面,这对于理解Hibernate如何与Web应用程序交互至关重要。 在 Hibernate 中,登录页面通常涉及以下关键组件和概念: 1. **实体类(Entity Class)**: 这是与数据库表相对应的...

    Spring与Hibernate集成中的session

    - 创建`Session`:`SessionFactory.openSession()`或`SessionFactory.getCurrentSession()`(在已配置的事务环境下)。 - 事务开始:`Session.beginTransaction()`。 - 数据操作:如`Session.save()`, `Session....

    hibernate-spring整合

    在Spring中,我们可以使用SessionFactory的openSession()或getCurrentSession()方法获取Session实例。 4. **事务管理**: Spring提供PlatformTransactionManager接口,可以用来管理数据库事务。在Hibernate整合中,...

    Hibernate说明文档.rar_ajax_hibernate

    通过使用Hibernate,开发者可以将数据库操作与业务逻辑解耦,使代码更加简洁、高效。本指南将深入探讨Hibernate的基本概念、配置、实体映射、查询语言以及与其他技术如Ajax的集成。 ### 1. Hibernate入门 ...

Global site tag (gtag.js) - Google Analytics