天天看点

Spring 5 中文解析数据存储篇-理解Spring事物抽象

Spring核心篇章: Spring 5 中文解析之核心篇-IoC容器 Spring 5 中文解析核心篇-IoC容器之依赖关系 Spring 5 中文解析核心篇-IoC容器之Bean作用域 Spring 5 中文解析核心篇-IoC容器之自定义Bean性质 Spring 5 中文解析核心篇-IoC容器之BeanDefinition继承与容器拓展点 Spring 5 中文解析核心篇-IoC容器之基于注解的容器配置 Spring 5 中文解析核心篇-IoC容器之类路径扫描和组件管理 Spring 5 中文解析核心篇-IoC容器之JSR330标准注解 Spring 5 中文解析核心篇-IoC容器之基于Java容器配置 Spring 5 中文解析核心篇-IoC容器之Environment抽象 Spring 5 中文解析核心篇-IoC容器之ApplicationContext与BeanFactory Spring 5 中文解析核心篇-IoC容器之Resources Spring 5 中文解析核心篇-IoC容器之数据校验、数据绑定和类型转换 Spring 5 中文解析核心篇-IoC容器之SpEL表达式 Spring 5 中文解析核心篇-IoC容器之AOP编程(上) ") Spring 5 中文解析核心篇-IoC容器之AOP编程(下) Spring 5 中文解析核心篇-IoC容器之Spring AOP API Spring测试篇章: Spring 5 中文解析测试篇-Spring测试 Spring 5 中文解析核心篇-集成测试之概要和集成测试注解 Spring 5 中文解析核心篇-集成测试之TestContext(上) Spring 5 中文解析核心篇-集成测试之TestContext(中) Spring 5 中文解析测试篇-集成测试之TestContext(下) Spring 5 中文解析测试篇-Spring MVC测试框架 Spring 5 中文解析测试篇-WebTestClient Spring存储篇章: Spring 5 中文解析数据存储篇-Spring框架的事物支持模型的优势 完整 电子书地址

1.2 理解Spring框架事物抽象

Spring事务抽象的关键是事务策略的概念。事务策略由

TransactionManager

定义,特别是用于命令式事务管理的

org.springframework.transaction.PlatformTransactionManager

接口和用于响应式事务管理的

org.springframework.transaction.ReactiveTransactionManager

接口。以下清单显示了

PlatformTransactionManager

API的定义:

public interface PlatformTransactionManager extends TransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}           

尽管你可以从应用程序代码中以

编程方式

使用它,但它主要是一个服务提供接口(SPI)。由于

PlatformTransactionManager

是接口,因此可以根据需要轻松对其进行模拟或存根。它与

JNDI

之类的查找策略无关。与Spring框架IoC容器中的任何其他对象(或bean)一样,定义了

PlatformTransactionManager

实现。这一优点使Spring框架事务成为值得抽象的,即使在使用

JTA

时也是如此。与直接使用

JTA

相比,你可以更轻松地测试事务代码。

同样,为了与Spring的理念保持一致,可以由任何

PlatformTransactionManager

接口方法抛出的

TransactionException

未检查异常(也就是说,它扩展了

java.lang.RuntimeException

类)。事物基础架构故障几乎总是致命的。在极少数情况下,应用程序代码实际上可以从事务失败中恢复,应用程序开发人员仍然可以选择捕获和处理

TransactionException

。实际一点是,开发人员没有被迫这样做。

getTransaction(..)

方法根据

TransactionDefinition

参数返回

TransactionStatus

对象。如果当前调用堆栈中存在匹配的事务,则返回的

TransactionStatus

可能表示一个新事务或一个现有事务。后一种情况的含义是,与Java EE事务上下文一样,

TransactionStatus

与执行线程相关联。

从Spring框架5.2开始,Spring还为使用响应式类型或

Kotlin

协程的响应式应用程序提供了事务管理抽象。以下清单显示了由

org.springframework.transaction.ReactiveTransactionManager

定义的事务策略:

public interface ReactiveTransactionManager extends TransactionManager {

    Mono<ReactiveTransaction> getReactiveTransaction(TransactionDefinition definition) throws TransactionException;

    Mono<Void> commit(ReactiveTransaction status) throws TransactionException;

    Mono<Void> rollback(ReactiveTransaction status) throws TransactionException;
}           

响应式事务管理器主要是服务提供接口(SPI),尽管你可以从应用程序代码中以

使用它。由于

ReactiveTransactionManager

是接口,因此可以根据需要轻松对其进行模拟或存根。

TransactionDefinition

接口指定:

  • 传播:通常,事务范围内的所有代码都在该事务中运行。但是,如果在已存在事务上下文的情况下运行事务方法,则可以指定行为。例如,代码可以在现有事务中继续运行(常见情况),或者可以暂停现有事务并创建新事务。Spring提供了

    EJB

    CMT

    熟悉的所有事务传播选项。要了解有关Spring中事务传播的语义的信息,请参阅 事务传播
  • 隔离:此事务与其他事务的工作隔离的程度。例如,此事务能否看到其他事务未提交的写入?
  • 超时:该事务在超时之前将运行多长时间,并由基础事务基础结构自动回滚。
  • 只读状态:当代码读取但不修改数据时,可以使用只读事务。在某些情况下,例如使用

    Hibernate

    时,只读事务可能是有用的优化。

这些设置反映了标准的事物概念。如有必要,请参考讨论事务隔离级别和其他核心事务概念的资源。了解这些概念对于使用Spring框架或任何事务管理解决方案至关重要。

TransactionStatus

接口为事务代码提供了一种控制事务执行和查询事务状态的简单方法。这些概念应该很熟悉,因为它们对于所有事务API都是通用的。以下清单显示了

TransactionStatus

接口:

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

    @Override
    boolean isNewTransaction();

    boolean hasSavepoint();

    @Override
    void setRollbackOnly();

    @Override
    boolean isRollbackOnly();

    void flush();

    @Override
    boolean isCompleted();
}           

无论你在Spring中选择声明式还是编程式事务管理,定义正确的

TransactionManager

实现都是绝对必要的。通常,你可以通过依赖注入来定义此实现。

TransactionManager

实现通常需要了解其工作环境:

JDBC

JTA

Hibernate

等。

TransactionManager

JDBC

JTA

Hibernate

等。以下示例显示了如何定义本地

PlatformTransactionManager

实现(在这种情况下,使用纯

JDBC

)。

你可以通过创建类似于以下内容的bean来定义

JDBC

数据源:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>           

然后,相关的

PlatformTransactionManager

Bean定义将引用

DataSource

定义。它应类似于以下示例:

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>           

如果你在Java EE容器中使用

JTA

,则可以使用通过

JNDI

获得的容器

DataSource

以及Spring的

JtaTransactionManager

。以下示例显示了

JTA

JNDI

查找:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee
        https://www.springframework.org/schema/jee/spring-jee.xsd">

    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/>

    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />

    <!-- other <bean/> definitions here -->

</beans>           

JtaTransactionManager

不需要了解数据源(或任何其他特定资源),因为它使用了容器的全局事务管理基础结构。

dataSource

bean的先前定义使用jee名称空间中的标记。有关更多信息,参考 JEE Schema

你还可以轻松使用

Hibernate

本地事务,如以下示例所示。在这种情况下,你需要定义一个

Hibernate

LocalSessionFactoryBean

,你的应用程序代码可使用该

Hibernate

LocalSessionFactoryBean

获取

Hibernate

Session

实例。

DataSource

bean定义与先前显示的本地

JDBC

示例相似,因此在以下示例中未显示。

如果通过

JNDI

查找数据源(由任何非

JTA

事务管理器使用)并由Java EE容器管理,则该数据源应该是非事务性的,因为Spring框架(而不是Java EE容器)管理事务。

在这种情况下,

txManager

bean是

HibernateTransactionManager

类型。就像

DataSourceTransactionManager

需要引用数据源一样,

HibernateTransactionManager

需要引用

SessionFactory

。以下示例声明了

sessionFactory

txManager

bean:

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
        <list>
            <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
        </value>
    </property>
</bean>

<bean id="txManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>           

如果使用

Hibernate

和Java EE容器管理的

JTA

事务,则应使用与前面的

JDBC

JTA

示例相同的

JtaTransactionManager

,如以下示例所示:

<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>           

JTA

,则无论使用哪种数据访问技术(无论是

JDBC

Hibernate

JPA

或任何其他受支持的技术),事务管理器定义都应该相同。这是由于

JTA

事务是全局事务,它可以征用任何事务资源。

在所有这些情况下,无需更改应用程序代码。你可以仅通过更改配置来更改事务的管理方式,即使更改意味着从本地事务转移到全局事务,反之亦然。

作者

个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号:青年IT男 获取最新技术文章推送!

博客地址:

http://youngitman.tech

CSDN:

https://blog.csdn.net/liyong1028826685

微信公众号:

Spring 5 中文解析数据存储篇-理解Spring事物抽象

技术交流群:

Spring 5 中文解析数据存储篇-理解Spring事物抽象