Spring-事务模型及实现资源同步

2019-08-11  本文已影响0人  夏与清风
1、事务管理概述

事务是恢复和并发控制的基本单位。事务具有四个属性(ACID):原子性、一致性、隔离性、持久性。

2、事务模型
1)全局事务

全局事务使用户可以使用多个事务资源,通常是关系数据库和消息队列。应用程序服务器通过JTA管理全局事务,JTA的UserTransaction通常需要来自JNDI,即需要使用JNDI才能使用JTA。
全局事务将限制应用程序代码的重用,因为JTA通常只在应用程序服务器环境中可用。

2)本地事务

本地事务是特定于资源的,如与JDBC连接关联的事务。本地事务更易使用,缺点是不能在多个事务资源上工作。如使用JDBC连接管理事务的代码无法在全局JTA事务中运行。由于应用程序服务器不参与事务管理,无法保证跨多个资源的正确性。
另外一个缺点是本地事务对编程模型是侵入式的。

3)spring框架的一致性编程模型

spring解决了全局事务和本地事务的缺点,它使开发人员可以在任何环境中使用一致的编程模型。
spring框架提供了声明式和编程式事务管理。通过编程式事务管理,开发人员可以使用spring框架事务抽象,它可以在任何事务基础设施上运行。使用声明式模型,通常会写很少与事务管理相关的代码,不依赖于spring框架事务API或任何其他事务API。
spring事务抽象的核心是事务策略,事务策略由org.springframework.transaction.PlatformTransactionManager接口定义。

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
    void commit(TransactionStatus var1) throws TransactionException;
    void rollback(TransactionStatus var1) throws TransactionException;
}

PlatformTransactionManager是一个接口,可以根据需要轻松进行Morck或Stub,它不受JNDI等查找策略的舒服。
PlatformTransactionManager接口是任何方法都可以抛出未检查的TransactionException,开发人员可以自行选择捕获和处理TransactionException。
getTransaction(TransactionDefinition var1)方法根据TransactionDefinition参数返回一个TransactionStatus对象。返回的TransactionStatus对象可能代表一个新的事务,或是一个已存在的事务。
TransactionDefinition接口定义:

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    int getPropagationBehavior();
    int getIsolationLevel();
    int getTimeout();
    boolean isReadOnly();
    @Nullable
    String getName();
}

TransactionStatus接口为事务代码提供了一种简单的方法来控制事务执行和查询事务状态。

public interface TransactionStatus extends SavepointManager, Flushable {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    void flush();
    boolean isCompleted();
}

示例:定义本地PlatformTransactionManager实现。
定义JDBC数据源:

<bean id="dataSource" class="org.apache.commons.dbcp2.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>

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

如果使用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 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/jee
        http://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"/>
    <!-- 省略其他bean定义 -->
</beans>

JtaTransactionManager不需要了解DataSource或任何其他特定资源,它使用容器的全局事务管理基础设施。dataSource的定义使用jee命名空间中的<jee:jndi-lookup/>标签。

3、通过事务实现资源同步
Connection conn = DataSourceUtils.getConnection(dataSource);

如果现有的事务已经有一个同步到它的连接,则返回该实例。否则方法调用会触发创建一个新的连接,该连接与任何现有事务同步,并可以用于同一事务中的后续重用。
一旦使用了spring的JDBC、JPA或hibernate支持,通常不会使用DataSourceUtils或其他帮助类,因为通过spring抽象,比直接使用相关的API更简便。

--参考文献《Srping5开发大全》

上一篇下一篇

猜你喜欢

热点阅读