04 Spring 声明式事务
2022-11-23 01:29:00 1 举报
04 Spring 声明式事务
作者其他创作
大纲/内容
<b>什么是事务?</b>
把一组业务当成一个业务来做;
要么都成功,要么都失败,保证业务操作完整性的一种<b>数据库机</b>制。
<b>Spring JdbcTemplate</b>
什么是JdbcTemplate?
<b>更加方便</b>的操作JDBC
为不同类型的<b>JDBC操作</b>提供了<b>模板方法</b>
它是<b>线程安全</b>的,但建议呢最好还是<b>一个dao对应一个jdbcTemplate</b>
配置及应用
1、添加依赖
pom依赖如下1:
pom依赖如下2:
从下图可以看出,orm已依赖了jdbc和tx(事务)的jar,无需再另外引入
2、配置扫描包
xml配置:
3、JdbcTemplate 配置数据源
a.新建db配置文件
b.JdbcTemplate注入数据源
4、测试获取数据源bean和jdbcTemplate的bean
代码示例:
5、查询单个值:
代码示例:
6、查询实体:
代码示例:
7、查询List实体:
代码示例:
8、新增:
代码示例:
9、修改:
代码示例:
10、删除:
代码示例:
11、具名参数处理:
1、spring配置中新注入NamedParameterJdbcTemplate
2、使用实例:
<b>事务的四大特性</b>
<b><font color="#2196f3">ACID</font></b>
<b><font color="#2196f3">A 原子性</font></b>:
原子性指的是 在一组业务操作下 要么都成功 要么都失败
换句话说:在一组增删改查的业务下 要么都提交 要么都回滚
<b><font color="#2196f3">C 一致性</font></b>:
事务前后的数据要保证数据的一致性
换句话说:在一组的查询业务下 必须要保证前后关联数据的一致性
<b><font color="#2196f3">I 隔离性</font></b>:
在并发情况下 事物之间要相互隔离
<b><font color="#2196f3">D 持久性</font></b>:
数据一旦保存就是持久性的<br>
<b>在事务控制方面的分类</b>
<b><font color="#2196f3">编程式事务</font></b>
在代码中直接加入处理事务的逻辑,可能需要在代码中显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法
代码示例:
<b><font color="#2196f3">声明式事务</font></b>
在方法的外部添加注解或者直接在配置文件中定义
将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理
Spring的AOP恰好可以完成此功能:
事务管理代码的固定模式作为一种横切关注点
通过AOP方法模块化,进而实现声明式事务
<b>声明式事务的配置</b>
<b>1、先配置一个事务管理器,并将数据注入</b>
<b>xml配置:</b>
<b>2、基于注解方式的事务,开启事务的注解驱动</b>
如果基于注解的和xml的事务都配置了会以注解的优先
<b>3、声明事务,进行测试</b>
<b>使用<font color="#2196f3">@Transactional</font>注解应该写在哪:</b>
<b>1、</b>可以<b><font color="#ff9800">标记在类上</font></b>面,则当前类所有的方法都运用上了事务
<b>2、<font color="#ff9800">标记在方法</font><font color="#2196f3">,</font></b>则只是当前方法运用事务<br>
<b>3、</b>也可以<b><font color="#ff9800">类和方法上面同时都存在</font></b>,
a. 如果类和方法都存在@Transactional会以方法的为准
b. 如果方法上面没有@Transactional会以类上面的为准
<font color="#e57373">建议:</font>
@Transactional写在方法上面,控制粒度更细
@Transactional写在业务逻辑层上,因为只有业务逻辑层才会有嵌套调用的情况
<b>代码示例:</b>
<b>事务配置的属性</b>
<b>1、设置隔离级别</b>
<b>解决并发事务所产生的问题:</b>
并发概念:<span style="font-weight: normal;">同一个时间,多个线程同时进行请求,但并不是所有并发情况都会产生问题</span>
<b>什么情况下产生并发问题</b>:在并发情况下,对同一个数据(变量、对象)进行读写操作才会产生并发问题
<b>并发会产生什么问题?</b>
<b><font color="#2196f3">脏读</font></b>
<b>指:</b>一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生的数据不一致的问题
<b>举例:</b>张三发工资了1000,张三和老婆都取钱了,老婆早0、0001微弱的优势取200元,这个时候张三发现剩800,但是呢这个时候老婆操作出问题了,账户里边还是1000元
<b>解决:</b>
设置张三只读已提交结果1000元
使用<b><font color="#ff9800">@Transactional(isolation = Isolation.READ_COMMITTED)</font></b>
<font color="#ff9800"><b>读已提交</b>:</font><b><font color="#ff9800">READ COMMITTED</font></b>
要求Transaction01只能读取Transaction02已提交的修改
<b><font color="#2196f3">不可重复读</font></b>
<b>指:</b>一个事务中,多次读取相同的数据, 但是读取的结果不一样, 会在本事务中产生数据不一致的问题。
<b>举例:</b>张三发工资了1000,张三和老婆都取钱了,张三早0、0001微弱的优势读1000元,这个时候张三老婆取了200元剩800,操作成功了,这个时候张三想再确认下又读了一下,发现账户上只有800了,从张三这个层面呢,前后读取的数据前后不一致问题,但第二次读取到的数据又不是脏数据,这里问题是在一次请求里张三读到了两个数据不一致的问题<br>
<b>解决:</b>
设置张三在读数据时,设置行锁,这个时候他老婆就不能操作取钱
使用<b><font color="#ff9800">@Transactional(isolation = Isolation.REPEATABLE_READ)</font></b>
确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。(行锁)
<font color="#2196f3"><b>幻影读</b></font>
<b>指:</b>一个事务中,多次对数据进行整表数据读取(统计),但是结果不一样, 会在本事务中产生数据不一致的问题
<b>举例:</b>张三公司给多少员工统计发了多少钱,人事部门和财务部门同时操作,人事部门以0.001秒的微弱优势统计到3000元,这个时候呢财务部门工资还没发完呢,这个时候财务部门给赵六也发了1000元,这个时候人事部门再统计一次变成了4000元,就出现了一个事务中前后查询结果不一致问题<font color="#e57373">(此现象与<b>不可重复读</b>相似)</font>
<b>解决:</b>
当人事统计查询时,禁止财务进行工资发放
使用<b><font color="#ff9800">@Transactional(isolation = Isolation.SERIALIZABLE)</font></b>
确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。(表锁)<br>
<b>不可重复读和幻影读的区别:</b>
两者问题相似
<b><font color="#2196f3">不可重复读</font></b>:只需要锁行,且重点在于update和delete操作
<b><font color="#2196f3">幻读</font></b>:需要锁表,且重点在于insert操作
<b>隔离级别的比较:</b>
比较如图:
从<b><font color="#2196f3">并发安全</font></b>考虑:SERIALIZABLE>REPEATABLE_READ>READ_COMMITTED
从<b><font color="#2196f3">运行效率</font></b>考虑:READ_COMMITTED>REPEATABLE_READ>SERIALIZABLE
<b>默认的事务隔离级别</b>(不同数据库不同默认)
<b><font color="#2196f3">MySQL</font></b>:
默认:<b><font color="#ff9800">REPEATABLE-READ</font></b>(可重复读)
查询事务级别:
<b><font color="#2196f3">ORACLE</font></b>:
默认:<b><font color="#ff9800">READ_COMMITTED</font></b>(读已提交)
ORACLE:不支持设置可重复读级别
查询事务级别:
针对<b>查询</b>操作:
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场<br>景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持(如:设置不可重复度、幻影读级别)。
<b>2、事务的传播特性</b>
指:一个事务方法调用另一个事务方法的时候,即:事务嵌套的时候
spring的事务传播行为:
<b>REQUIRED(默认)</b>:
调用它的方法不存在事务时: 它开启新的事务
调用它的方法存在事务:融合到外部事务中 <br>
<b>适用增删改查</b>
<b>SUPPORTS</b>:
调用它的方法不存在事务时:不开启新的事务,如:query方法
调用它的方法存在事务:融合到外部事务中
<b>适用查询</b>
<b>REQUIRES_NEW</b>:
调用它的方法不存在事务时:开启新的事务
调用它的方法存在事务:挂起外部事务,创建新的事务
适用于内部事务和外部事务不存在业务关联的情况,如日志在外部事务操作异常后不影响日志的数据记录
<font color="#e57373">建议:在这个场景下时,不建议内外事务方法在同一个类中</font>
NOT_SUPPORTED
调用它的方法不存在事务时:不开启新的事务
调用它的方法存在事务:挂起外部事务
<font color="#e57373">不常用</font>
NEVER
调用它的方法不存在事务时:不开启新的事务
调用它的方法存在事务:抛出异常
<font color="#e57373">不常用</font>
MANDATORY
调用它的方法不存在事务时:抛出异常
调用它的方法存在事务:融合到外部事务中
<font color="#e57373">不常用</font>
<b>3、超时属性(timeout)</b>
<b><font color="#2196f3">timeout</font></b>:指定事务等待的最长时间(秒)
当前事务访问数据时,有可能访问的数据被别的数据进行加锁的处理,那么此时事务就必须等待,如果等待时间过长给用户造成的体验感差
代码示例:
<b>4、设置事务只读(readOnly)</b><br>
<b><font color="#2196f3">readonly</font></b>:只会设置在查询的业务方法中
同:connection.setReadOnly(true) 通知数据库,当前数据库操作是只读,数据库就会对当前只读做相应优化<br>
当将事务设置只读 就必须要你的业务方法里面没有增删改。
代码示例:
5、异常属性(noRollbackFor/rollbackFor)
<b><font color="#2196f3">noRollbackFor</font></b>:设置哪些异常不回滚
<b><font color="#2196f3">rollbackFor</font></b>:设置哪些异常回滚
使用示例:
<b>基于xml的事务配置</b>
声明事务切入的所有方法
代码示例:
明确切点匹配到的方法哪些方法需要使用事务
代码示例:
<b>注解方式和XML方式的比较</b>
注解方式:控制力度更细
XML方式:一次配置一劳永逸的方式,同时还增强项目业务方法的约定
0 条评论
下一页