Spring事务 作者:哇塞大嘴好帅(我爱大嘴网)

Spring事务 作者:哇塞大嘴好帅(我爱大嘴网)

我爱大嘴好帅(我爱大嘴网)
我爱大嘴好帥(我愛大嘴網)

1.事务的特性(ACID)

1.原子性(Atomicity)

2.一致性(Consistency)

3.隔离性(isolation)

4.持久性(Durability)

1.原子性(Atomicity)

​ 比如张三给李四5块钱,然后李四给赵四3块钱。原子性就是这些步骤要不都执行要不都别执行,如果某一步出现问题就回滚撤销。

2.一致性(Consistency)

​ 数据保证在业务上是正确的

3.隔离性(isolation)

​ 两个事务的执行要互不影响,互不干扰,

4.持久性(Durability)

​ 一旦提交事务成功,数据会到数据库持久化保存,也就是拥有保存。

Spring事务管理机制

Spring事务时在数据库事务的基础上进行封装扩展的,主要特性如下

​ 1.支持原有的数据库事务的隔离级别,加入了事务传播的概念

​ 2.提供国歌事务的合并或隔离的功能

​ 3.提供声明式事务,让业务代码与事务分离,事务变得更加易用(AOP)

Spring提供了事务相关的接口

Spring事务管理高层抽象主要包含3个接口,Spring的事务主要通过他们三个共同完成

TransactionDefinition

​ 事务定义: 事务定义信息(隔离、传播、只读、超时)

PlatformTransactionManager

​ 事务管理器,主要用于平台相关事务的管理、

TransactionStatus

​ 获取事务的运行状态

1.1PlatformTransactionManager 事务管理器介绍

参考文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/PlatformTransactionManager.html

commit方法提交事务

getTransaction获取事务状态 里面的TransactionDefinition是事务的定义 ,通过事务的定义信息去获取状态

rollback回滚

Spring为不同的持久层框架提供了不同的PlaformTransactionManaeg的接口实现

事务说明
org.springframework.jdbc.datasource.DataSourceTransactionManager使用Spring JDBC或iBatis进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager使用Hibernate5.0半斤星星持久化数据时使用
org.springframework.orm.jpa.JpaTransactionManager使用JPA进行持久化时使用
org.springframework.jdo.JdoTransactionManager当持久化机制是Jdo时使用
org.springframework.trasanction.jta.JtaTransactionManager使用一个JTA实现来管理事务,在一个事务跨越多个资源必须使用.

DatasourceTransactionManager针对JdbcTemplate、Mybatis事务控制,使用Connection(连接)进行事务管理

开启事务connection.setAutoCommit(false),只有这个为false时候才能进行提交事务connection.commit() 、回滚事务connection.rollback();

1.2 TransactionDefinition 事务定义信息

参考文档:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/TransactionDefinition.html

**getIsolationLevel ** 获取隔离级别

getName 获取当前事务的昵称

getPropagationBehavior 获取事务传播行为

getTimeout 获取超时时间,默认值是-1.-1就是不超时

isReadOnly 判断事务是否只读

常用的事务隔离级别

Isolation Leavelmeaning
DEFAULT使用后端数据库默认的隔离别(Spring中的选择项)
READ_UNCOMMITED允许你读取还未提交的未改变的数据。可能导致脏读、幻读、不可重复读
READ_COMMITTED允许在并发事务已经提交后读取。可防止脏读,但幻读和不重复读依然可以发生
REPEATABLE_READ对相同子弹的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读依然可能发生.
SERIALIZABLE100%服从ACID的隔离级别,确保不发生脏读、幻读、不可重复读。这在所有的隔离级别中是最慢的,他是典型的通过完全锁定在事务张设计的数据表来完成的。

DEFAULT是基于你选择的数据库,来选择你数据库的默认隔离级别

如:Mysql默认隔离级别为REPEATABLE_READ

​ Oracle默认隔离级别 READ_COMMITTED

propagation behavior事务传播行为

7种事务传播级别

事务传播行为类型说明
PROPAGATION_REQUIRED支持当前事务,如果不存在就创建一个
PROPAGATION_SUPPORTS支持当前事务,如果不存在,就不使用事务
PROPAGATION_MANDATORY支持当前事务,如果不存在,抛出异常
PROPAGATION_REQUIRES_NEW如果有事务存在,挂起当前事务,创建一个新的事务
PROPAGATION_NOT_SUPPORTED以非事务方式运行,如果有事务存在,挂起当前事务
PROPAGATION_NEVER以非事务方法运行,如果有事务存在,抛出异常
PROPAGATION_NESTED如果当前事务存在,则嵌套事务执行,只针对DataSourceTransactionManager

主要分为三大类:

PROPAGATION_REQUIRED(default) ,PROPAGATION_SUPPORTS ,PROPAGATION_MANDATORY

​ 支持当前事务,A调用B,如果A事务还存在,那么A and B就处于同一个事务,事务默认的传播级别为REQUIRED

PROPAGATION_REQUIRES_NEW,PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER

​ 不会支持原来的事务,如A调用B,如果A事务存在,B肯定不会和A处于一个事务。

常用的事务传播行为:REQUIRES_NEW

PROPAGATION_NESTED 不常用

​ 嵌套事务,只对DatasourcetransactionManager有效,底层使用JDBC的SavePoint机制,允许在同一个事务设置保存点,回滚保存点

常用的事务传播行为:NESTED

REQUIRED NESTED REQUIRES_NEW的区分

​ required 只有一个事务(默认,推荐)

​ requires_new 存在两个事务,如果事务存在,挂起事务,重新又开启一个新的事务

​ nested 嵌套事务,事务可以设置保存点,回滚到保存点,选择提交or回滚

2.Spring事务管理

2.1编程式事务

​ 编程式事务就是通过纯代码控制事务,手动提交手动回滚

2.1.1 xml配置
<!--事务管理器-->
<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--事务管理的模板-->
<bean id="transactionTemplate" class="org.springframework.transaction,support.TransactionTemplate">
    <property name="transactionManager" ref="transactionManager"></property>
</bean>
2.1.2 注解配置
@ComponentScan("com.dazuizui")
public class TransactionConfig{
    /**
     *  事务管理器
     */
	@Bean
    public TransactionTemple transactionTemplate(DataSourceTransactionManager dataSourceTransactionManager){
        TransactionTemplate transactionTemplate = new TransactionTemplate();
        transactionTemplate.setTransactionManager(transactionTemplate);
        return transactionTemplate;
    }
    
    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dm = new DataSourceTransactionManager();
        dm.setDataSource(dataSource);
        return dm;
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDtaSource(dataSource);
        return jdbcTemplate;
    }
    
    @Bean
    public DtaSource dataSource(){
        BasicDataSource ds = new BasicDataSource();
        ds.seturl("url");
        ds.setDriverClassName("com.mysql.jdbc.Driver")
        ds.setUsername("username");
        ds.setPassowrd("password");
        return ds;
    }
}
2.1.3 实现
/**
 * 通过xml配置使用
 */
@Test
public void test1(){
    ApplicationContext ca = new CLassPathXmlApplicationContext("applicationContext.xml");
    UserSerivce userBean = ca.getBean(UserSerivce.class);
    bean.test1();//执行数据库操作
}

/**
 * 执行注解配置文件模式
 */
public void test2(){
    AnnotationConfigApplicationContext ac= new AnnotationConfigApplicationContext(TransactionConfig.class);
        UserSerivce userBean = ca.getBean(UserSerivce.class);
    bean.test1();//执行数据库操作
}

将调用数据库事务通过Lambda表达式写在transactiontemplate.execute()方法内进行事务事务管理

@Autowired
private TransactionTemplate transactiontemplate		//事务管理器
    
public void test1(){
    transactiontemplate.execute(status - > {
       userMapper.zhuanqian();	//调用数据库小张转钱给小明
        int x = 10086;
        if(x==10086)
            throw new RuntimeException("error");
        userDao.income();	//小明收入小张转的钱
        return null;
    });
}

2.2 申明式事务

2.2.1基于AspectJ xml的配置方式

使用该申明式定要删除配置文件中的事务管理模板中的配置。

​ 也就是这个

<!--事务管理器-->
<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

添加一个事务定义的配置和AOP的配置

<!--事务管理器-->
<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--增强事务的属性配置-->
    <td:attributes>
    	<!--
			isolation: default,事务隔离级别
			propagation: 事务传播行为
			read-onlu: fase,是否只读
			timeout: -1,    超时-1为默认值
			no-rollback-for: 发生那些异常不回滚
			rollback-for:	 发生哪些异常滚事务
		-->
        	<tx:method name="方法名" isolation="DEFAULT" propagation="REQUIRED">	
           	<!--save开头的方法全部增强-->
            <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED">
                
        </tx:method>
    </td:attributes>
</tx:advice>

<!--aop配置定义切面和切点信息-->
<aop:config>
	<!--定义切点:那些类的方法应用加强-->
    <aop:pointct expression="excution(* com.dazuizui.beans.service..*.*(..))"
                 id="mypointct"/>
    <!--定义切面-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="mypointcut"></aop:advisor>
</aop:config>

说一下Spring事务的配置:

​ 第一种方法基于XML的配置方法,需要配置事务管理器,然后在配置事务的增强

​ 事务定义主要配置,事务隔离级别、事务传播行为、是否只读、超时时间、发生那些异常不回滚、发生哪些异常滚事务

​ 再通过aop:config设置切面和切入点

2.2.2 注解方法声明式事务
@ComponentScan("com.dazuizui")
@EnableTransactionManagement		//开启注解事务
public class TransactionConfig{    
    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager dm = new DataSourceTransactionManager();
        dm.setDataSource(dataSource);
        return dm;
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDtaSource(dataSource);
        return jdbcTemplate;
    }
    
    @Bean
    public DtaSource dataSource(){
        BasicDataSource ds = new BasicDataSource();
        ds.seturl("url");
        ds.setDriverClassName("com.mysql.jdbc.Driver")
        ds.setUsername("username");
        ds.setPassowrd("password");
        return ds;
    }
}

如果你想使用事务那么就在Service类的上面加入**@Transactional**就是当前类下所有方法都进行事务管理,如果在方法上使用,那么就这个方法受到事务管理。

说一下Spring事务的配置:

​ 基于注解的,在类上或者方法上添加**@Transactional**

3.Spring 传播特性

3.1 什么是传播特性? What is propagation charecteristics?

​ 当一个事务方法被另一个事务方法调用时(方法A调用方法B),这个事务方法应该如何进行。

for example:

@Service
public class test1{
    @Transactional
    public void function1(){
        System.out.println("funcion 1 method");
    	function2();
    }
    @Transactional
    public void function2(){
        System.out.println("function 2 medhod");
    }
}

3.2 Spring的7中传播特性 7 kinds of propagation chanrecteristics of Spring

传播行为(propagation)描述(discribe)
PROPAGATION_REQUIRED默认事务类型,如果没有就新建一个事务;如果有就加入当前事务。
PROPAGATION_SUPPORTS如果没有事务就非事物执行,如果有事务就使用当前事务
PROPAGATION_MANDATORY如果没有事务就抛出异常,如果有就使用当前事务
PROPAGATION_REQUIRES_NEW如果没有事务就非事务执行,所有有就将事务挂起
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER如果有事务就抛出异常,如果没有就非事务执行
PROPAGATION_NESTED如果没有事务就创建一个事务;如果有就在当前事务种嵌套其他事务
3.2.1详细解说7种传播特性

​ 使用注解设置传播特性例如

​ @Transaction(propagation=Propagation.SUPPORTS)

​ @Transaction(propagation=Propagation.NEVER)

3.2.1.1 PROPAGATION_NEVER

​ 如果function1 或者 function2存在事务那么直接抛出异常

for example

@Service
public class test1{
    @Transactional
    public void function1(){
        System.out.println("funcion 1 method");
    	function2();
    }
    @Transactional
    public void function2(){
        System.out.println("function 2 medhod");
    }
}

这样会报错

@Service
public class test1{
    public void function1(){
        System.out.println("funcion 1 method");
    	function2();
    }
    public void function2(){
        System.out.println("function 2 medhod");
    }
}

这样就不会报错

3.2.1.2 PROPAGATION_NOT_SUPPORTED

​ 如果被调用方法发现调用它的方法存在事务那么就将事务挂起(我把你放一边,我做我的事情),

for example

@Service
public class test1{
    @Transactional
    public void function1(){
        System.out.println("funcion 1 method");
    	function2();
    }

    public void function2(){
        System.out.println("function 2 medhod");
    }
}

可以说PROPAGATION_NOT_SUPPORTED and PROPAGATION_NEVER 是死都不要事务

3.2.1.3 PROPAGATION_SUPPORTED

​ 你有事务我就用事务执行,你没有事务我就不按事务执行。

可以说propagation_not_supported是可有可无事务

3.2.1.4 propagation_requires_new

​ 不管有没有事务都必须创建一个事务,如果有事务,就将原来的事务挂起。我创建一个新的

for example

@Service
public class test1{
    @Transactional
    public void function1(){
        System.out.println("funcion 1 method");
    	function2();
    }
    @Transactional
    public void function2(){
        System.out.println("function 2 medhod");
    }
}

function2不管function1是否存在事务,我function2都必须创建一个事务,当我的事务走完了再去走function1的事务

​ 可以实现子影响父,但父不影响子的效果

3.2.1.5 propagation_nested

for example

@Service
public class test1{
    @Transactional
    public void function1(){
        System.out.println("funcion 1 method");
    	function2();
    }
    @Transactional
    public void function2(){
        System.out.println("function 2 medhod");
    }
}

如果function2出现了异常那么function1也跟着回滚

3.2.1.6 propagation_required (默认)

​ 如果没有事务我就创建一个事务,如果有事务那么我就用你的事务

3.2.1.7 propagation_mandatory

​ 如果没有事务我就报错,如果有事务我就用你的

propagation_mandatory 和 propagation_required 和propagation_nested 和 propagation_requires_new 必须有一个事务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哇塞大嘴好帅(DaZuiZui)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值