Spring系列:Spring事务处理与事务属性概述

前言
1.事务处理
1.1 什么是事务
1.2 事务编码的核心(不包含Spring框架的情况下的分析)
1.3 Spring事务开发编程(使用Spring框架实现事务)
2. Spring中的事务属性(Transaction Attribute)
2.1 什么是事务属性
2.2 如何添加事务属性
2.3 事务5大属性说明
2.4 事务属性配置总结

前言

  1. 本章主要对Sping的事务做一个简单的概述
    ▲. 事务处理简单介绍
    ▲. 事务属性的简单描述

1. 事务处理

1.1 什么是事务

  1. 什么是事务?
    ⑴ 事务:保证业务操作完整性的一种数据库机制
    —>"保证业务操作完整性"说明:一个业务当中涉及到的多步操作,要么一起成功,要么
    一起失败,而且不能产生相互影响。

  2. 事务的4个特点:A,C,I,D
    ⑴ A:原子性
    ⑵ C:一致性
    ⑶ I:隔离性
    ⑷ D:持久性

1.2 事务编码的核心(不包含Spring框架的情况下的分析)

. 1. 如何控制事务。
–>这里我们暂时不考虑’Spring’,这里讲的是在开发的过程中控制的这个事务。
⑴ 作为’事务’的控制来讲,你采用不同的持久化技术,它控制的方式是不一样的。 JDBC技术是一种方式,那换成mybatis控制事务又是另外一种方式。
~~-------------------------------------------------------------------------------------
⑵ 控制事务的持久化技术分析:
➀. JDBC控制事务的方式:
Connection.setAutoCommit(false); //开启事务
Connection.commit(); //提交事务
Connection.rollback(); //回滚事务
—>其核心就是全部依附与连接对象(Connection)
~~-------------------------------------------------------------------------------------
➁.Mybatis控制事务的方式:
Mybatis开启事务是自动的,无需我们担心。我们只要去处理事 务的提交和回滚即可。
sqlSession(connection).commit(); //提交
sqlSession(connection).rollback(); //回滚
—>扩展:在mybatis的sqlSession底层也封装了’connection’(连接对象)
~~-------------------------------------------------------------------------------------
➂. 因此:不管你使用什么方式去控制事务,就只有三个步骤:开启 + 提交 + 回滚事务。
—>当然,不同的持久化技术它所"开启,提交,回滚"方式是有差异的。
~~-------------------------------------------------------------------------------------
⑶ 结论:在我们现在所使用的主流的持久化解决方案当中,不管用JDBC还是Mybatis,乃至日后的’JPA’,其实控制事务的底层都是’Connection’对象来完成的。

1.3 Spring事务开发编程(使用Spring框架实现事务)

1. Spring事务开发编程步骤,如下所示↓:
⑴ 第一步:搭建开发环境(pomx.ml引入jar包)
<!--Spring与事务整合的jar包-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.1.14.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.14.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.2</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.18</version>
</dependency>
<!--oracle数据库驱动-->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0.4</version>
</dependency>
<!--mybatis依赖包-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>

⑵ 第二步:编码:原始功能 + 额外功能 + 组装
--->以下配置都是在Spring的配置文件完成的(applicationContext.xml)
<!-- 第一步:原始对象 -->
<bean id="userService" class="com.mybatishg.service.UserServiceImpl">
    <!--UserDAO注入进来
        通过MapperScannerConfigure会帮我们创建UserDAO的实现类,因此我们在'ref=“”'中值的引入UserDAO
        只需要命名为:首字母小写即可,引入进来
    -->
    <property name="userDAO" ref="userDAO"/>
</bean>

<!--
    开发额外功能:
    Spring提供了一个'DataSourceTransactionManager'类,我们直接诶对这个类进行
    配置使用即可,来实现事务的额外功能。但是在配置的过程中我们需要为它注入连接池。
-->
<!--
第二步:额外功能
第三步:切入点是由注解来完成的@Transaction注解
 -->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--进行连接池的注入-->
    <property name="dataSource" ref="dataSource"/>
</bean>
<!--
第四步:进行组装
组装切面:使用以'tx'结尾的标签
transaction-manager="dataSourceTransactionManager":里面的值就是我们上面定义的"额外功能"的id
-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

⑶ 第三步:使用@Transaction注解配置切入点
/**
 * 在类头部加上:@Transactional 则类下面所有方法都加上了事务
 */
@Transactional
public class UserServiceImpl implements UserService {
    /**
     * UserServiceImpl 类需要DAO,就代表依赖DAO,因此就将DAO作为'UserServiceImpl类'的成员变量,并配置Get/Set方法
     * 最后通过Spring的配置文件进行注入(赋值)
     *
     */
    private UserDAO userDAO;

    public UserDAO getUserDAO() {
        return userDAO;
    }

    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    /**
     * 注意:UserServiceImpl是原始对象,因此它应该只负责核心功能。
     * 而核心功能只包括两个:业务运算 + DAO调用
     *
     */
    public void register(User user) {
        userDAO.save(user);
    }
}

⑷ 第四步:UserService接口
public interface UserService {
    public void register(User user);
}

⑸ 第五步:UserDAO + User
public interface UserDAO {
    public void save(User user);
}


public class User implements Serializable {

    private Integer id;
    private String userCode;
    private String username;
    private String userPassword;
    private Integer gender;
    private Date birthday;
    //Get/Set配置
    
}



⑹ 第六步:测试
/**
 * 用于测试:Spring的事务处理
 */
@Test
public void test2() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
    UserService userService = (UserService) ctx.getBean("userService");
    User user = new User();
    user.setId(15);
    user.setUserCode("jiuqiansui");
    user.setUsername("小明");
    user.setUserPassword("jqs123456");
    user.setGender(2);
    user.setBirthday(new Date());
    userService.register(user);
}
--->运行test2()程序,执行事务的插入操作。


2. Spring中的事务属性(Transaction Attribute)

2.1 什么是事务属性

  1. 什么是事务属性?
    1.1 属性
    ⑴ 属性:描述物体特征的一系列值。
    (性别,身高,体重…)
    —>只要是物体,它就有特性,而有特征就需要从多个维度去来描述它,进而体现
    出这个物体的特点。对于事务来讲它也是一样的我们前面仅仅是给service加上了事务,
    但是这个事务具有什么样的特征呢,其实就需要我们所说的事务属性>来进行描述。
    ~~-------------------------------------------------------------------------
    1.2 事务属性
    ⑵ 事务属性:描述事务特征的一系列值。
    (事务当然和人的描述不一样,人的特征比较复杂,他可能有各个维>度,而作为事务来讲,
    在描述事务特征的时候其实它的维度比较简单,主要从五个维度(属>性)来描述),
    五个维度属性描述事务,如下所示↓:
    1.隔离属性
    2.传播属性
    3.只读属性
    4.超时属性
    5.异常属性

2.2 如何添加事务属性

  1. 如何添加事务属性?
    —>在编程当中我们如何为事务添加上这5个事务属性,进而描述事务的一些特点。
    ⑴ 我们实现实现’事务’编程的步骤中,对于’切入点’的实现我们使用的是’@Transaction()注解’那么在这个注解当中,我们就可以为事务设置上对应的"5个事务属性"。

  2. 利用@Transaction()注解,给事务添加属性
    ⑴ @Transaction(isloation=) -->设置事务的’隔离属性’,并在等号后面对属性赋值
    ⑵ @Transaction(propagation=) -->设置’传播属性’,并在等号后面对属性赋值
    ⑶ @Transaction(readOnly=) -->设置’只读属性’,并在等号后面对属性赋值
    ⑷ @Transaction(timeout= ) -->设置’超时属性’,并在等号后面对属性赋值
    ⑸ @Transaction(rollbackFor=, noRollbackFor=,)
    —>对于’异常属性’,它在添加属性的时候它有两个对应的值:rollbackFor=, noRollbackFor=,

  3. 我们现在至少了解添加’事务属性’的方式,就事在’@Transaction()'这个注解里面添加事务的属性分别是什么。

2.3 事务5大属性说明

1.事务的5大属性
⑴ 属性一:隔离属性(ISOLATION). 隔离属性的概念:它描述了事务解决并发问题的特征。
⑵ 属性二;传播属性(PROPAGATION). 传播属性的概念:他描述了事务解决嵌套问题的特征。
	➁. 事务嵌套出现的场景:service调用service的情况有可能出现	
	事务嵌套。
	➂. (一般情况service调用的是DAO,但是随着系统规模的不断扩
	大,所处理的业务复杂度不断提高,很有可能也会出现service调用
	service的情况). 日后开发中:推荐传播属性的使用方式
		a. 增删改方法:直接使用默认值REQUIRED。(即使			 
		用'@Transaction()'注解后,对于里面的值写不写都无所谓,	
		因为他默认传播属性的值就是:REQUIRED)
		b. 查询操作:需要我们显示指定传播属性的值为:SUPPORTS
⑶ 属性三:只读属性(readOnly)'只读属性'的作用:针对于只进行查询操作的业务方法,可以加
	入只读属性,提供运行效率。
	a. 为什么'只读属性'可以提高运行效率呢?原因:我们之前说过加
	上事务为了保证并发安全,那我们就要加各种各样的锁,那么显然这
	个锁会将一个并行话的工作变成串行,他一定会影响运行效率,而当
	我们如果确定了这个方法只进行查询操作的话,我们为它加上'只读
	属性'那么它就不会在加各种各样其他额外的锁了。当然它的运行
	效率也就提高了。

⑷ 属性四:超时属性(readOnly)
	➀ 超时属性:指定了事务等待的最长时间。
	➁ 为什么事务要进行等待呢?
	比如:客户A发起了对'数据1'这行数据的访问,那么为了防止这	
	行'数据1'在客户A访问的过程当中,产生'不可重复读'的问题,所	
	以作为客户A这个事务来讲它为这行数据加了一把'行锁',它把这行
	数据给锁住了。如果此时客户B也发起了对这行数据的访问,那么此
	时客户B就需要等待客户A访问完才可以去访问这行'数据1',那这个
	等待到底等待多长时间?那这个事最终是由'超时属性'来决定的。
	---->'超时属性'决定了客户B在等待的过程当中它最长时间能等待
	多少秒。
	➂ 为什么事务进行等待的最终解释:
	-->当前事务访问数据时,有可能访问的数据被别的事务进行加锁的	
	处理,那么此时本事务就必须进行等待。
	➃ 超时属性:等待的时间是以'秒'为单位。
	--->若我们设置了超时等待的时间为2秒,那么2秒过去了那么此时	
	就会抛出对于的异常了。
	➄ 超时属性的应用:
	@Transactional(timeout=2)  #表示:设置超时等待时间为2秒

⑸ 属性五:异常属性
	➀ 对于Spring事务处理异常的过程中,我们是否可以设置'对于	
	RuntimeException及其子类'采用的是提交的策略,而'对于
	Exception及其子类'采用的是回滚的策略--->这就要通过事务的'异
	常属性'来进行设置了。
	➁ rollbackFor{java.lang.Exception,xxx,xxx}    
	--->(事务回滚策略设置,括号内可设置多个异常处理)
	➂ noRollbackFor{java.lang.RuntimeException,xxx,xxx}  
	--->(事务提交策略设置,括号内可设置多个异常处理)
	➃ 事务异常属性的使用方式(register()抛出的异常,设置异常
	属性处理),代码如下所示↓:
	@Transactional(rollbackFor = {java.lang.Exception.class},noRollbackFor = {java.lang.RuntimeException.class})
	public class UserServiceImpl implements UserService {
		....代码....
	}
	➄ 注意点:在日后的开发过程当中,这种'rollbackFor 
	'和'noRollbackFor'的设置我们很少在实战当中进行这样的应用。
	因为他必定比较麻烦,我们一般都采用默认的方式。而且针对于事务
	有问题产生异常之后,我们基本上还是按照回滚的方式进行操作的。
	所以在后续开发过程当中,我们建议使用"默认值",同时建议大家使
	用'RuntimeException及其子类'-->这样Spring才会对于这种异常
	执行回滚操作。
	➅ 建议:实战中使用RuntimeExceptin及其子类使用事务异常属性
	的默认值


2.4 事务属性配置总结

  1. 事务属性常见配置总结
    ⑴ 隔离属性(ISOLATION):建议对于此属性直接使用默认值
    ⑵ 传播属性(PROPAGATION):Required(使用默认值)
    REQUIRED值(增删改) + SUPPORTS值(查)
    ⑶ 只读属性(readOnly):readOnly false 增删改 | true 查询操作
    ⑷ 超时属性(timeout):默认值 -1
    ⑸ 异常属性:默认值

  2. 后续在实战当中建议是:
    ⑴ 对于增删改操作:直接写"@Transaction()“就够了。
    —>因为我们直接写’@Transaction()注解’就相当于’隔离属性使用默认值’,‘传播属性使用Required也是默认值’,‘只读属性默认值readOnly=false’,‘超时异常默认值-1’,‘异常属性默认值’
    ⑵ 对于查询操作:需要根据它的特点在:
    '@Transaction(propagation=Propagation,SUPPORTS,readOnly=true)注解’这样设置值即可。
    ⑶ 因此对于事务”@Transaction()"的使用直接记住上面’增删改’和’查询’直接使用上面对于情况即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值