首页 php教程 PHP开发 Spring事务抽象

Spring事务抽象

Nov 22, 2016 pm 03:17 PM
spring

1    介绍Spring框架事务管理

全面的事务支持是使用Spring框架令人信服的原因。Spring框架为事务管理提供一致性抽象,拥有以下好处:

一致性编程模型跨不同事务APIs,例如,Java事务API(JTA)、JDBC、Hibernate、Java持久化API(JPA)和Java数据对象(JDO)。

支持声明式事务管理。

比复杂事务APIs(例如,JTA)更简单。

完美的与Spring的数据访问抽象集成。

2    Spring框架的事务支持模型的优点

传统上,Java EE开发人员有两种可选的事务管理方式:全局或本地事务,都有各自的局限性。

2.1    全局事务

全局事务让你能使用多个事务资源,通常是关系型数据库和消息队列。应用程序通过JTA管理全局事务,这是一个笨重的API。而且,JTA UserTransaction通常需要来自JNDI,意味着你需要使用JNDI。显然,使用全局事务会限制应用程序代码的重用,因为JTA通常只在应用程序服务器环境有效。

以往,使用全局事务的首选方式是通过EJB CMT(容器管理事务):CMT是声明式事务管理。EJB CMT清除了相关事务的JNDI查找,不过EJB自己需要使用JNDI。它清除大多数(但不是所有)需要编写Java代码控制事务。重要的缺点是,CMT捆绑JTA和应用程序服务器环境。同时,它只有使用EJBs实现业务逻辑,或至少在事务EJB门面中时才有效。

2.2    本地事务

本地事务时特定资源,例如,事务关联JDBC连接。本地事务易于使用,但有明显缺点:它们不能跨多个事务资源。例如,使用JDBC连接管理事务不能运行在全局JTA事务中。因为应用程序服务器没有负责事务管理,它不保证跨资源的正确性。另一个缺点是本地事务时入侵式编程模型。

2.3    Spring框架的一致性编程模型

Spring解决了全局和本地事务的缺点。它让开发人员在任意环境使用一致性编程模型。开发人员只需编写自己的代码,它能抽离不同环境中的不同的事务管理。Spring框架提供声明式和编程式事务管理。大多数用户喜欢声明式事务管理,这也是推荐的。

使用编程式事务管理,开发人员使用Spring框架事务抽象,能运行在任意底层事务之上。使用首选的声明式模型,开发人员通常写很少或不写事务管理代码,因此,不依赖于Spring框架事务API,或其它事务API。

3    理解Spring框架事务抽象

Spring事务抽象的关键是事务策略的概念。事务策略通过org.springframework.transaction.PlatformTransactionManager接口定义:

public interface PlatformTransactionManager {

 

    TransactionStatus getTransaction(

            TransactionDefinition definition) throws TransactionException;

 

    void commit(TransactionStatus status) throws TransactionException;

 

    void rollback(TransactionStatus status) throws TransactionException;

}

这主要是服务提供接口(SPI),尽管它能在你的代码中使用编程模型。因为PlatformTransactionManager是一个接口,它易于模拟(mocked)和存根(stubbed)。它不需要像JNDI一样查找策略。PlatformTransactionManager实现像Spring IoC容器中定义的其它对象一样。这个好处让Spring框架事务值得抽象,甚至是使用JTA时。事务代码比直接使用JTA易于测试。

PlatformTransactionManager接口方法抛出的TransactionException是未检测异常(即,继承java.lang.RuntimeException)。事务失败是致命性的。很少情况,应用程序代码能实际从事务失败中恢复,应用程序开发人员能选择捕获并处理TransactionException。优点在于开发人员不必强制这样做。

getTransaction(..)方法依赖于TransactionDefinition参数返回TransactionStatus对象。返回的TransactionStatus可以代表一个新事务,或如果匹配事务在当前调用栈中存在则代表已存在的事务。其实就是后面这种情况,正如Java EE事务上下文,TransactionStatus关联可执行的事务。

TransactionDefinition接口说明:

Isolation(事务隔离级别):事务隔离级别。例如,该事务是否能读取其它的未提交事务?

Propagation(事务传播):通常,所有代码执行在事务范围将运行在事务中。然而,你有一个选项可以指定当事务上下文已存在时事务方法执行的行为。例如,代码能继续运行在已存在的事务中(通常情况);或已存在的事务暂停,创建一个新事务。

事务超时:该事务运行多长时间后失效,并通过底层事务自动回滚。

只读状态:当你的代码读取但不修改数据时,可以使用只读事务。在某些情况下,只读事务有利于优化,例如,当你使用Hibernate时。

这些设置反应标准事务概念。底层这些概念是使用Spring框架或任意事务管理解决方案不可或缺的。

TransactionStatus接口为事务代码提供简单的方式控制可执行事务和查询事务状态:

public interface TransactionStatus extends SavepointManager {

 

    boolean isNewTransaction();

 

    boolean hasSavepoint();

 

    void setRollbackOnly();

 

    boolean isRollbackOnly();

 

    void flush();

 

    boolean isCompleted();

 

}

 无论你是否选择Spring中的声明式或编程式事务管理,定义正确的PlatformTransactionManager实现是必不可少的。你通常通过依赖注入定义该实现。

PlatformTransactionManager通常需要知道工作的环境:JDBC、JTA、Hibernate等等。下面是定义本地PlatformTransactionManager的例子。

定义JDBC DataSource:

destroy-method="close">

    

    

    

   

PlatformTransactionManager定义引用DataSource定义:

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

   

 

如果你在Java EE容器中使用JTA,那么你可以通过使用JNDI和Spring的JtaTransactionManager获取容器的DataSource:

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">

 

   

   

    

JtaTransactionManager不需要知道DataSource,或任意特定资源,因为它使用容器的全局事务管理。

你也能使用Hibernate的本地事务。在这种情况下,你需要定义Hibernate的LocalSessionFactoryBean,你的应用程序代码将使用它获取Hibernate Session实例。

这种情况下,txManager bean是HibernateTransactionManager。正如DataSourceTransactionManager需要引用DataSource一样,HibernateTransactionManager需要引用SessionFactory:

    

    

        

            org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml

        

    

    

        

            hibernate.dialect=${hibernate.dialect}

        

    

   

 如果你使用Hibernate和Java EE容器管理JTA事务,那么你只用使用JtaTransactionManager:

在所有这些情况下,应用程序代码不需要改变。你仅仅需要改变配置来改变如何管理事务。

4    使用事务同步资源

现在应该清楚如何创建不同的事务管理器,和它们如何链接需要同步事务的相关资源(例如,DataSourceTransactionManager链接DataSource,HibernateTransactionManager链接SessionFactory等等)。

4.1    高级同步方式

首选方式是使用Spring的高级模板基于持久化集成APIs或使用带有事务的本地ORM APIs——感知工厂bean或代理管理本地资源工厂。这些事务感知解决方案内部处理资源创建、重用、清理、资源事务同步选项和异常映射。因此,数据访问代码没有处理这些任务,但可以关注非样板式持久化逻辑。通常,你使用本地ORM API或通过使用JdbcTemplate获取模板。

4.2    低级同步方式

例如,DataSourceUtils(JDBC)、EntityManagerFactoryUtils(JPA)、SessionFactoryUtils(Hibernate)、PersistenceManagerFactoryUtils(JDO)存在底层同步方式。当你想应用程序代码直接处理本地持久化APIs,你使用这些类确保获取Spring框架管理的实例,事务是(可选)同步的,发生在进程中的异常正确映射一致性API。

例如,在JDBC的情况下,传统的JDBC方式在DataSource上调用getConnection()方法,你可以使用Spring的org.springframework.jdbc.datasource.DataSourceUtils:

Connection conn = DataSourceUtils.getConnection(dataSource);

如果已存在的事务已经有一个连接同步(链接)它,实例被返回。否则,方法调用触发器创建新的连接,(可选)同步任意已存在的事务,后续在相同事务中重用。

这种方式不需要Spring事务管理(事务同步是可选的),因此,无论你是否使用Spring管理事务你都能使用它。

当然,一旦你使用Spring的JDBC支持、JPA支持或Hibernate支持,你通常不喜欢使用DataSourceUtils或其它的帮助类。

4.3    TransactionAwareDataSourceProxy

在底层,已经存在TransactionAwareDataSourceProxy类。这是目标DataSource代理,包装目标DataSource到感知Spring管理事务。为此,它类似于Java EE服务器提供的传统JNDI DataSource。

5    声明式事务管理

Spring框架的声明式事务管理让Spring面向切面编程(AOP)成为可能,尽管,Spring框架发布包以模板形式自带事务切面代码,一般需要理解AOP。

5.1    理解Spring框架的声明式事务实现

通过元数据驱动事务通知(当前基于XML或注解)。AOP联合事务元数据产生AOP代理,使用TransactionInterceptor联合适当的PlatformTransactionManager实现驱动事务环绕方法调用。

QQ图片20161122092324.png

5.2    声明式事务实现的例子

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd">

    

    

        

            

            

            

            

        

    

 

    

        

        

    

 

   

        

        

        

        

    

 

   

        

    

 5.3    回滚声明式事务

默认情况下,只有抛出运行时异常或Error时导致Spring事务回滚。检查异常不导致Spring事务回滚。

你能明确配置事务回滚的异常类型。

    

        

        

    

你也能指定事务不会滚的异常类型:

    

       

        

   

5.4    为不同的bean配置不同的事务语义

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd">

 

    

        

        

        

        

    

 

    

        

            

            

        

    

 

    

        

            

        

    

5.5    设置

默认设置:

事务传播设置是REQUIRED

事务隔离级别是DEFAULT

事务是读/写

事务超时时间默认为底层事务系统的超时时间,或如果不支持超时就没有

任意RuntimeException异常触发回滚,任意检查Exception不触发

你能改变这些默认设置;嵌套在标签中的标签的各种属性:

QQ图片20161122092324.png

5.6    使用@Transactional

开启注解管理事务:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop.xsd">

 

   

   

   

        

    

 

    

Service声明注解:

@Transactional

public class DefaultFooService implements FooService {

 

    Foo getFoo(String fooName);

 

    Foo getFoo(String fooName, String barName);

 

    void insertFoo(Foo foo);

 

    void updateFoo(Foo foo);

}

@Transactional设置:

QQ图片20161122092324.png

@Transactional的多事务管理器:

public class TransactionalService {

 

    @Transactional("order")

    public void setSomething(String name) { ... }

 

    @Transactional("account")

    public void doSomething() { ... }

}

 

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    ...

    

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

    ...

    

自定义简称注解

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Transactional("order")

public @interface OrderTx {

}

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Transactional("account")

public @interface AccountTx {

}

5.7    事务传播

PROPAGATION_REQUIRED

QQ图片20161122092324.png

当设置事务传播为PROPAGATION_REQUIRED时,为每个方法创建一个逻辑事务范围。每个逻辑事务范围能单独决定只回滚状态,外部事务范围逻辑独立于内部事务范围。当然,在标准的PROPAGATION_REQUIRED情况下,所有这些范围将映射相同的物理事务。因此,只回滚标记设置在内部事务范围不影响外部事务发生的实际提交。

然而,在这种情况下,内部事务范围设置为只回滚标记,外部事务没有决定回滚,因此回滚是意想不到的。相应的UnexpectedRollbackException抛出。

PROPAGATION_REQUIRES_NEW

QQ图片20161122092324.png

对比PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW使用完全独立的事务。在这种情况下,底层物理事务是不同的,因此,能独自提交或回滚,外部事务的回滚状态不受内部事务的影响。

PROPAGATION_NESTED

使用一个能回滚到多个保存点的物理事务。这种回滚允许内部事务范围触发它的范围回滚,外部事务能够继续物理事务,尽管一些操作已经回滚。该设置通常映射到JDBC保存点,因此,只能用于JDBC资源事务。

6    编程式事务管理

Spring框架提供两种编程式事务管理:

使用TransactionTemplate(推荐)

使用PlatformTransactionManager直接实现

6.1    使用TransactionTemplate

TransactionTemplate采用与其它Spring模板(例如,JdbcTemplate)相同的方式。

public class SimpleService implements Service {

 

    private final TransactionTemplate transactionTemplate;

 

    public SimpleService(PlatformTransactionManager transactionManager) {

        Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");

        this.transactionTemplate = new TransactionTemplate(transactionManager);

    }

 

    public Object someServiceMethod() {

        return transactionTemplate.execute(new TransactionCallback() {

            public Object doInTransaction(TransactionStatus status) {

                updateOperation1();

                return resultOfUpdateOperation2();

            }

        });

    }

}

如果没有返回值,则使用TransactionCallbackWithoutResult类:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

    protected void doInTransactionWithoutResult(TransactionStatus status) {

        updateOperation1();

        updateOperation2();

    }

});

在业务代码中回滚:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

 

    protected void doInTransactionWithoutResult(TransactionStatus status) {

        try {

            updateOperation1();

            updateOperation2();

        } catch (SomeBusinessExeption ex) {

            status.setRollbackOnly();

        }

    }

});

指定事务设置:

public class SimpleService implements Service {

 

    private final TransactionTemplate transactionTemplate;

 

    public SimpleService(PlatformTransactionManager transactionManager) {

        Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");

        this.transactionTemplate = new TransactionTemplate(transactionManager);

        this.transactionTemplate.setIsolationLevel(

        TransactionDefinition.ISOLATION_READ_UNCOMMITTED);

        this.transactionTemplate.setTimeout(30); // 30秒

   }

}

使用Spring XML配置TransactionTemplate:

class="org.springframework.transaction.support.TransactionTemplate">

   

   

6.2    使用PlatformTransactionManager

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

def.setName("SomeTxName");

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);

try {

    // 执行业务逻辑

} catch (MyException ex) {

    txManager.rollback(status);

    throw ex;

}

txManager.commit(status);

7    选择编程式还是声明式管理事务?

如果你只有少量事务操作选择编程式事务管理。

8    事务绑定事件

从Spring 4.2开始,监听器事件可以绑定到事务阶段。

@Componentpublic class MyComponent {

 

    @TransactionalEventListener

    public void handleOrderCreatedEvent(CreationEvent creationEvent) {

          ...

    }

 

}

TransactionalEventListener注解暴露phase属性允许定制监听事务阶段。有效的阶段是:BEFORE_COMMIT、AFTER_COMMIT(默认)、AFTER_ROLLBACK和AFTER_COMPLETION。 


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

编程新范式,当Spring Boot遇上OpenAI 编程新范式,当Spring Boot遇上OpenAI Feb 01, 2024 pm 09:18 PM

2023年,AI技术已经成为热点话题,对各行业产生了巨大影响,编程领域尤其如此。人们越来越认识到AI技术的重要性,Spring社区也不例外。随着GenAI(GeneralArtificialIntelligence)技术的不断进步,简化具备AI功能的应用程序的创建变得至关重要和迫切。在这个背景下,"SpringAI"应运而生,旨在简化开发AI功能应用程序的过程,使其变得简单直观,避免不必要的复杂性。通过"SpringAI",开发者可以更轻松地构建具备AI功能的应用程序,将其变得更加易于使用和操作

利用Spring Boot以及Spring AI构建生成式人工智能应用 利用Spring Boot以及Spring AI构建生成式人工智能应用 Apr 28, 2024 am 11:46 AM

Spring+AI作为行业领导者,通过其强大、灵活的API和先进的功能,为各种行业提供了领先性的解决方案。在本专题中,我们将深入探讨Spring+AI在各领域的应用示例,每个案例都将展示Spring+AI如何满足特定需求,实现目标,并将这些LESSONSLEARNED扩展到更广泛的应用。希望这个专题能对你有所启发,更深入地理解和利用Spring+AI的无限可能。Spring框架在软件开发领域已经有超过20年的历史,自SpringBoot1.0版本发布以来已有10年。现在,无人会质疑,Spring

spring编程式事务有哪些实现方式 spring编程式事务有哪些实现方式 Jan 08, 2024 am 10:23 AM

spring编程式事务的实现方式:1、使用TransactionTemplate;2、使用TransactionCallback和TransactionCallbackWithoutResult;3、使用Transactional注解;4、使用TransactionTemplate和@Transactional结合使用;5、自定义事务管理器。

Java Spring怎么实现定时任务 Java Spring怎么实现定时任务 May 24, 2023 pm 01:28 PM

java实现定时任务Jdk自带的库中,有两种方式可以实现定时任务,一种是Timer,另一种是ScheduledThreadPoolExecutor。Timer+TimerTask创建一个Timer就创建了一个线程,可以用来调度TimerTask任务Timer有四个构造方法,可以指定Timer线程的名字以及是否设置为为守护线程。默认名字Timer-编号,默认不是守护线程。主要有三个比较重要的方法:cancel():终止任务调度,取消当前调度的所有任务,正在运行的任务不受影响purge():从任务队

Spring Boot与Spring Cloud的区别与联系 Spring Boot与Spring Cloud的区别与联系 Jun 22, 2023 pm 06:25 PM

SpringBoot和SpringCloud都是SpringFramework的扩展,它们可以帮助开发人员更快地构建和部署微服务应用程序,但它们各自有不同的用途和功能。SpringBoot是一个快速构建Java应用的框架,使得开发人员可以更快地创建和部署基于Spring的应用程序。它提供了一个简单、易于理解的方式来构建独立的、可执行的Spring应用

Spring 最常用的 7 大类注解,史上最强整理! Spring 最常用的 7 大类注解,史上最强整理! Jul 26, 2023 pm 04:38 PM

随着技术的更新迭代,Java5.0开始支持注解。而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架。

Spring如何设置事务隔离级别 Spring如何设置事务隔离级别 Jan 26, 2024 pm 05:38 PM

Spring设置事务隔离级别的方法:1、使用@Transactional注解;2、在Spring配置文件中设置;3、使用PlatformTransactionManager;4、在Java配置类中设置。详细介绍:1、使用@Transactional注解,在需要进行事务管理的类或方法上添加@Transactional注解,并在属性中设置隔离级别;​2、在Spring配置文件等等。

从零开始学Spring Cloud 从零开始学Spring Cloud Jun 22, 2023 am 08:11 AM

作为一名Java开发者,学习和使用Spring框架已经是一项必不可少的技能。而随着云计算和微服务的盛行,学习和使用SpringCloud成为了另一个必须要掌握的技能。SpringCloud是一个基于SpringBoot的用于快速构建分布式系统的开发工具集。它为开发者提供了一系列的组件,包括服务注册与发现、配置中心、负载均衡和断路器等,使得开发者在构建微

See all articles