Hibernate——事务处理和并发机制

在Java世界中,有两种定义明确的机制来处理JDBC中的事务:JDBC本身和JTA。Hibernate支持两种与事务集成并允许应用程序管理物理事务的机制。

每个会话的事务处理由org.hibernate.resource.transaction.spi处理。事务协调器契约,它由org.hibernate.resource.transaction.spi构建TransactionCoordinatorBuilder(事务协调生成器)服务。

本地事务(JDBC):本机的事务

全局事务(JTA):跨越多个虚拟机的事务,会使用容器管理事务(CMT),并且一定要服务器支持,不同的服务器有着不同的支持

全局事务又分为:

  • Bean管理的的事务(BMT):BMT主要是通过手工编程来实现事务的开启、提交和回滚,相对于CMT来说虽然增加了工作量,但是控制力度更细,而且更加灵活,我们可以再出现异常的时候回滚事务
  • 容器管理事务(CMT):自动创建、提交的事务,也就是全自动化事务

我们可以通过在hibernate配置文件中设置hibernate.transaction.coordinator_class属性来配置hibernate使用JDBC的事务还是,JTA的事务,如果没有设置这个属性,那么默认为JDBC事务,当我们调用JTA的事务但未设置hibernate.transaction.coordinator_class属性为JTA系统就会抛出错误

Hibernate直接使用JDBC连接和JTA资源,不添加任何额外的锁定行为。Hibernate不会锁定内存中的对象。使用Hibernate时,数据库事务的隔离级别定义的行为不会更改。Hibernate会话充当事务范围的缓存,提供可重复读取,以便按标识符和查询进行查找,从而加载实体。

要减少数据库中的锁争用,物理数据库事务需要尽可能短。长时间运行的数据库事务会阻止您的应用程序扩展到高度并发的负载。不要在最终用户级别的工作期间打开数据库事务,而是在最终用户级别的工作完成后打开它。这个概念被称为事务的后写入

提问:什么是物理事务

扫描二维码关注公众号,回复: 4998750 查看本文章

JTA配置(没看懂)

JTA提供了跨Session的事务管理能力

与JTA系统的交互在名为org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform的单个合同后面进行合并,该合同公开了对该系统的javax.transaction.TransactionManager和javax.transaction.UserTransaction的访问以及公开能够注册javax.transaction.Synchronization实例,检查事务状态等。

使用JTA必须有服务的支持不同的服务器需要不同的JtaPlatform支持,并且通过使用一个名为org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformResolver的服务来发现它应该使用的JtaPlatform。如果该文件不起作用,或者我们需要自定义服务来找到JTA的平台,则需要指定hibernate.transaction.jta.platform设置。Hibernate提供了许多JtaPlatform的实现,如下所示:

Atomikos

适用于Atomikos的JtaPlatform

Borland

Borland企业服务器的jtapplatform。

Bitronix

适用于Bitronix的JtaPlatform

JBossAS

JtaPlatform for Arjuna/JBossTransactions/Narayana when used within the JBoss/WildFly Application Server.

JBossTS

JtaPlatform for Arjuna/JBossTransactions/Narayana when used standalone.

JOnAS

JtaPlatform for JOTM when used within JOnAS.

JOTM

JtaPlatform for JOTM when used standalone.

JRun4

JtaPlatform for the JRun 4 Application Server.

OC4J

JtaPlatform for Oracle’s OC4J container.

Orion

JtaPlatform for the Orion Application Server.

Resin

JtaPlatform for the Resin Application Server.

SapNetWeaver

JtaPlatform for the SAP NetWeaver Application Server.

SunOne

JtaPlatform for the SunOne Application Server.

Weblogic

JtaPlatform for the Weblogic Application Server.

WebSphere

JtaPlatform for older versions of the WebSphere Application Server.

WebSphereExtended

JtaPlatform for newer versions of the WebSphere Application Server.

Hibernate Transaction API

要使用此API,您将从Session获取org.hibernate.Transaction。事务允许你期望的所有正常操作:开始,提交和回滚,它甚至暴露了一些很酷的方法,如:

Contextual sessions

大多数使用Hibernate的应用程序都需要某种形式的上下文会话,其中给定的会话在给定上下文的范围内有效。但是,跨应用程序,构成上下文的定义通常是不同的;不同的上下文定义了当前概念的不同范围。使用Hibernate 3.0版之前的应用程序倾向于使用本土的基于ThreadLocal的上下文会话,辅助类(如HibernateUtil),或利用第三方框架(如Spring或Pico),它们提供基于代理/拦截的上下文会话。

从版本3.0.1开始,Hibernate添加了SessionFactory.getCurrentSession()方法。最初,这假定使用JTA事务,其中JTA事务定义了当前会话的范围和上下文。鉴于众多独立JTA TransactionManager实现的成熟,大多数(如果不是全部)应用程序应该使用JTA事务管理,无论它们是否部署到J2EE容器中。基于此,您需要使用基于JTA的上下文会话。

前两个实现提供一个会话 对应 一个数据库事务编程模型,也就是说当事务完成时就会立刻关闭session这会导致出现问题。 Hibernate会话的开始和结束由数据库事务的持续时间定义。如果在没有JTA的普通Java SE中使用程序化事务划分,建议您使用Hibernate Transaction API从代码中隐藏基础事务系统。如果使用JTA,则可以使用JTA接口划分事务。如果在支持CMT的EJB容器中执行,则以声明方式定义事务边界,并且在代码中不需要任何事务或会话分界操作。有关更多信息和代码示例,请参阅事务和并发控制。

但是,从3.1版开始,SessionFactory.getCurrentSession()后面的处理现在是可插入的。为此,添加了一个新的扩展接口org.hibernate.context.spi.CurrentSessionContext和一个新的配置参数hibernate.current_session_context_class,以允许定义当前会话的范围和上下文的可插入性。

有关其合同的详细讨论,请参阅org.hibernate.context.spi.CurrentSessionContext接口的Javadocs。它定义了一个方法currentSession(),通过该方法,实现负责跟踪当前的上下文会话。开箱即用,Hibernate附带了这个接口的三个实现:

org.hibernate.context.internal.JTASessionContext

      当前会话由JTA事务跟踪和确定范围。此处的处理与旧的仅JTA方法完全相同。

org.hibernate.context.internal.ThreadLocalSessionContext

      当前会话由执行线程跟踪。有关更多详细信息,请参阅Javadocs。

org.hibernate.context.internal.ManagedSessionContext

      当前会话由执行线程跟踪。但是,您有责任使用此类的静态方法绑定和取消绑定Session实例;它不会打开,刷新或关闭会话。

通常,此参数的值只是命名要使用的实现类。但是,对于三个开箱即用的实现,有三个相应的短名称:jta,thread和managed。

事务模式(和反模式)

这是在单个线程中为每个数据库调用打开和关闭Session的反模式。就数据库事务而言,它也是一种反模式。将数据库调用分组为计划的序列。同样,在应用程序中的每个SQL语句之后都不要自动提交。Hibernate禁用或期望应用程序服务器立即禁用自动提交模式(因为每次提交都要进行session的关闭,这回导致session丢失,所以要禁用自动提交。数据库事务绝不是可选的。与数据库的所有通信必须由事务封装。避免自动提交行为以读取数据,因为许多小事务不可能比一个明确定义的工作单元执行得更好,并且更难以维护和扩展。

在此模式中,有一种定义当前会话的常用技术,以简化将此Session传递给可能需要访问它的所有应用程序组件的需要。Hibernate通过SessionFactory的getCurrentSession方法为这种技术提供支持。当前会话的概念必须具有定义当前概念有效的界限的范围。这是org.hibernate.context.spi.CurrentSessionContext合约的目的。

使用自动提交不会绕过数据库事务。相反,在自动提交模式下,JDBC驱动程序只是在隐式事务调用中执行每个调用。就好像您的应用程序在每次JDBC调用之后都调用了commit。

在此模式中,有一种定义当前会话的常用技术,以简化将此Session传递给可能需要访问它的所有应用程序组件的需要。Hibernate通过SessionFactory的getCurrentSession方法为这种技术提供支持。当前会话的概念必须具有定义当前概念有效的界限的范围。这是org.hibernate.context.spi.CurrentSessionContext合约的目的。

有2个可靠的定义范围:

  • 首先是JTA事务,因为它允许回调挂钩知道它何时结束,这使Hibernate有机会关闭Session并清理。这由org.hibernate.context.spi.CurrentSessionContext合约的org.hibernate.context.internal.JTASessionContext实现表示。使用此实现,将在该事务中第一次调用getCurrentSession时打开Session。第一次调用的时候打开session,请求周期的本身
  • 其次是这个应用程序请求循环本身。最好用org.hibernate.context.spi.CurrentSessionContext合约的org.hibernate.context.internal.ManagedSessionContext实现来表示。这里,外部组件负责管理当前会话的生命周期和范围。在这样一个范围的开头,调用ManagedSessionContext#bind()方法传入Session。最后,调用其unbind()方法。这些外部组件的一些常见示例包括:
    • javax.servlet.Filter implementation

    • AOP interceptor with a pointcut on the service methods

    • A proxy/interception container

对话(应用程序级事务)

猜你喜欢

转载自blog.csdn.net/qq_40929531/article/details/85681079