ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

声明式事务

2021-12-22 11:59:04  阅读:137  来源: 互联网

标签:回滚 级别 Transactional 事务 emp 注解 声明


JDBCTemplate

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O27BTim6-1640144673736)(.\img\009.jpg)]

xml配置 JDBCTemplate
<!--对JdbcTemplate进行IOC-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!--注入数据源对象-->
    <property name="dataSource" ref="dataSource"/>
</bean>
装配JDBCTemplate
 @Autowired
    private JdbcTemplate jdbcTemplate;
增改查操作
String sql = "insert into t_emp (emp_name,emp_salary) values (?,?)";
    jdbcTemplate.update(sql,"aobama",3000d);

String sql = "update t_emp set emp_name=?,emp_salary=? where emp_id=?";
    jdbcTemplate.update(sql,"aolafu",6000d,1);

//查询员工的个数
    String sql = "select count(emp_id) from t_emp";
    Long count = jdbcTemplate.queryForObject(sql, Long.class);
    System.out.println(count);
查询返回实体类

封装实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {
    private Integer empId;
    private String empName;
    private Double empSalary;
}

借助RowMapper完成查询

​ 在查询返回单列数据的时候,就该使用这个RowMapper

//查询多个员工信息,封装到List<Employee>中
    String sql = "select emp_id empId,emp_name empName, emp_salary empSalary from t_emp";
    List<Employee> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Employee.class));

    System.out.println(list);

声明式事务的概述

配置事务管理器

在spring的xml配置文件中我们需要配置事务管理器

<!--对事务管理者做IOC配置-->
<!--       
要开启注解方式声明式事务的支持
transaction-manager属性:表示使用哪个事务管理器对象来管理事务
如果你的事务管理器的id是transactionManager的话,可以省略该属性
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入数据源-->
    <property name="dataSource" ref="dataSource"/>
</bean>

注意:导入名称空间时有好几个重复的,我们需要的是 tx 结尾的那个。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2pkFDsR3-1640144673739)(.\img\008.jpg)]

在需要事务的方法上使用注解@Transactional就可以使用事务功能了

@Transactional
@Override
public void transfer(Integer fromId, Integer toId, Double money) {
    //1. 转出账户扣款
    accountDao.updateAccountMoney(fromId,-money);

    int num = 10/0;
    //2. 转入账户收款
    accountDao.updateAccountMoney(toId,money);
}

debug查看事务管理器中的关键方法

事务属性

只读属性

对一个查询操作来说,如果我们把它设置成只读,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。但是如果你的方法中执行写操作,那么就会报错

@Transactional(read-only=true)//read-only属性表示事务是否只读:默认值是false,如果设置为true那么当前事务中只能做数据库的读操作,不能做写操作
@Override
public void transfer(Integer fromId, Integer toId, Double money) {
    //1. 转出账户扣款
    accountDao.updateAccountMoney(fromId,-money);

    //int num = 10/0;
    //2. 转入账户收款
    accountDao.updateAccountMoney(toId,money);
}

如果在设置了只读的事务中进行写操作会抛出下面异常:

Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

如果将@Transactional注解放在类上

@Transactional注解在类级别标记,会影响到类中的每一个方法。同时,类级别标记的@Transactional注解中设置的事务属性也会延续影响到方法执行时的事务属性。除非在方法上又设置了@Transactional注解。

,离它最近的@Transactional注解中的事务属性设置生效。

PS:Spring 环境下很多场合都有类似设定,一个注解如果标记了类的每一个方法那么通常就可以提取到类级别。但是,如果不是类中的所有方法都需要用到事务,则绝不允许将@Transaction注解放在类上

超时属性

事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源,大概率是因为程序运行出现了问题(可能是Java程序或MySQL数据库或网络连接等等)。

此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行。

概括来说就是一句话:超时回滚,释放资源。

回滚和不回滚的异常属性

默认情况
@Transactional
@Override
public void transfer(Integer fromId, Integer toId, Double money) throws ClassNotFoundException{
    //1. 转出账户扣款
    accountDao.updateAccountMoney(fromId,-money);
    //什么是运行时异常:不需要在编译时处理的异常
    //什么是编译时异常:需要在编译时就进行处理的异常
	//默认情况是遇到运行时异常才回滚:
    Class.forName("com.mysql.jdbc.Driveraaaaaa");
    int num = 10/0;
    //2. 转入账户收款
    accountDao.updateAccountMoney(toId,money);
}
设置回滚的异常
  • rollbackFor属性:需要设置一个Class类型的对象
  • rollbackForClassName属性:需要设置一个字符串类型的全类名
@Transactional(rollbackFor = Exception.class)
设置不回滚的异常

在默认设置和已有设置的基础上,再指定一个异常类型,碰到它不回滚。

@Transactional(
    noRollbackFor = FileNotFoundException.class
)
如果回滚和不回滚异常同时设置
当两者范围不同

不管是哪个设置范围大,都是在大范围内在排除小范围的设定。例如:

  • rollbackFor = Exception.class
  • noRollbackFor = FileNotFoundException.class

意思是除了 FileNotFoundException 之外,其他所有 Exception 范围的异常都回滚;但是碰到 FileNotFoundException 不回滚。

事务隔离级别属性

事务特性

事务包括四大特性:ACID

  • A:原子性:事务是最小的工作单元,不可再分。
  • B:一致性:事务必须保证多条DML语句同时成功或者同时失败。
  • C:隔离性:事务A与事务B之间具有隔离。
  • D:持久性:持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束。
事务隔离级别

事务隔离性村子啊隔离级别,理论上隔离级别包括4个:

  • 第一级别:读未提交(READ UNCOMMITTED):对方事务还没有提交,我们那当前事务就可以读取到对方未提交的数据。读未提交存在脏读现象:表示读到了脏的数据。
  • 第二级别:读已提交(READ COMMITTED):对方事务提交之后的数据我方可以读取到。这种隔离级别解决了脏读现象。存在的问题:不可重复读。
  • 第三级别:可重复读(REPEATABLE READ)这种隔离级别解决了:不可重复读问题。存在问题:读取到的数据是幻象。
  • 第四级别:序列化/串行话读(SERIALIZABLE),解决所有的问题,但效率低。需要事务排队。
级别名字隔离级别脏读不可重复读幻读数据库默认隔离级别
1读未提交read uncommitted
2读已提交read committedOracle
3可重复读repeatable readMySQL
4串行化serializable最高的隔离级别
设置方式

在 @Transactional 注解中使用 isolation 属性设置事务的隔离级别。 取值使用 org.springframework.transaction.annotation.Isolation 枚举类提供的数值。

@Transactional(isolation = Isolation.READ_UNCOMMITTED)

事务传播行为属性

事务的传播行为要研究的是是当两个方法嵌套执行的时候,外层方法的事务能否传播到内层方法以及怎么传播到外层方法

propagation属性

@Transactional 注解通过 propagation 属性设置事务的传播行为。它的默认值是:

Propagation propagation() default Propagation.REQUIRED;

propagation 属性的可选值由 org.springframework.transaction.annotation.Propagation 枚举类提供:

名称含义
REQUIRED 默认值当前方法必须工作在事务中 如果当前线程上有已经开启的事务可用,那么就在这个事务中运行 如果当前线程上没有已经开启的事务,那么就自己开启新事务,在新事务中运行 所以当前方法有可能和其他方法共用事务 在共用事务的情况下:当前方法会因为其他方法回滚而受连累
REQUIRES_NEW 建议使用当前方法必须工作在事务中 不管当前线程上是否有已经开启的事务,都要开启
在业务层中声明两个内层方法
@Transactional(propagation = Propagation.REQUIRED)

测试 REQUIRED 模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5kx2tTwm-1640144673741)(./img/015.png)]

效果:内层方法A、内层方法B所做的修改都没有生效,总事务回滚了。

过滤器或拦截器等类似组件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MQSnTQAU-1640144673744)(./img/018.png)]

Spring5的新特性

相关注解

注解名称含义可标记位置
@Nullable可以为空@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@NonNull不应为空@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
@NonNullFields在特定包下的字段不应为空@Target(ElementType.PACKAGE) @TypeQualifierDefault(ElementType.FIELD)
@NonNullApi参数和方法返回值不应为空@Target(ElementType.PACKAGE) @TypeQualifierDefault({ElementType.METHOD, ElementType.PARAMETER})

整合junit5

导入依赖

在原有环境基础上增加如下依赖:

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.7.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.1</version>
</dependency>
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AtguiguSpringConfiguration.class)

使用复合注解

@SpringJUnitConfig(AtguiguSpringConfiguration.class)

总结

1 、Spring 框架概述
(1)轻量级开源 JavaEE 框架,为了解决企业复杂性,两个核心组成:IOC 和 AOP
(2)Spring5.2.6 版本
2 、IOC 容器
(1)IOC 底层原理(工厂、反射等)
(2)IOC 接口(BeanFactory)
(3)IOC 操作 Bean 管理(基于 xml)
(4)IOC 操作 Bean 管理(基于注解)
3 、Aop
(1)AOP 底层原理:动态代理,有接口(JDK 动态代理),没有接口(CGLIB 动态代理)
(2)术语:切入点、增强(通知)、切面
(3)基于 AspectJ 实现 AOP 操作
4 、JdbcTemplate
(1)使用 JdbcTemplate 实现数据库 curd 操作
(2)使用 JdbcTemplate 实现数据库批量操作
5 、事务管理
(1)事务概念
(2)重要概念(传播行为和隔离级别)
(3)基于注解实现声明式事务管理
(4)完全注解方式实现声明式事务管理
6 、Spring5 新功能
(1)整合日志框架
(2)@Nullable 注解
(3)函数式注册对象
(4)整合 JUnit5 单元测试框架
(5)SpringWebflux 使用

标签:回滚,级别,Transactional,事务,emp,注解,声明
来源: https://blog.csdn.net/weixin_42571010/article/details/122082255

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有