一,什么是事务
概念:在数据库操作中涉及到事务的概念。通俗一点说,在MySQL中,事务就是一组sql语句的集合,集合中有多条sql语句,可能是insert,update,select,delete,我们希望这些多个sql语句都能成功,或者都失败,这些sql语句的执行是一直的,作为一个整体执行。
事务的特点(ACID)
原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
二,在什么时候想到使用事务
当我们的操作涉及到多个表,或者是多个sql语句的增加insert删除delete修改update的时候,
需要保证这些语句都是成功才能完成我们的功能;或者保证这些语句都失败,保证操作是符合要求的。最明了的例子就是转账,从A账户转到B账户中,要保证从A中扣除的金额一定要加到B里去。如果A到B转账成功,那么A扣B加,要保证A和B的账户是均衡的。如果A向B转账的过程中扣款失败了,那就应该把操作都回退,A也不扣,B也不加,保证A和B中账户数据的平衡。
在java代码中写程序,控制事务,此时事务应该放在哪里呢?
在开发中,事务是放在serviceImpl类的业务方法上的,因为一个业务方法可能涉及到多个dao的调用,执行多个sql语句。
三,使用JDBC访问数据库,还是Mybatis访问数据库怎么处理事务
JDBC访问数据库,处理事务:连接对象Connection conn;事务提交 conn.commit ();事务回滚:conn.rollback ();
Mybatis 访问数据库,处理事务:事务提交:SqlSession.commit ();事务回滚:SqlSession.rollback ();
四, 问题3中事务的处理方式有什么不足
(1)不同的数据库访问技术,处理事务的对象,方法不同。JDBC使用的是Connection对象,Mybatis访问对象使用的事
SqlSession。方法不同就需要了解不同数据库访问技术使用事务的原理。
(2)掌握多种数据库中事务的处理逻辑,知道什么时候提交,什么时候回滚。
(3)处理事务的多种方法。
总结:多种数据库的访问技术,有不同的事务处理的机制,对象,方法。
五,怎么解决问题4中的这些不足
spring提供了一种处理事务的统一模型,能使用统一的步骤,方式,完成多种不同数据库访问技术的事务处理。
使用spring的事务处理机制,可以完成MyBatis访问数据库的事务处理。
使用spring的事务处理机制,可以完成Hibernate访问数据库的事务处理。
六,spring框架中提供的事务处理方案(基于AOP)
1、项目的构建可参考:https://blog.csdn.net/qq_36763419/article/details/113925334
2,基于注解的方案(@Transactional):适用于中小型项目 >>【关键代码】
spring框架用aop实现给业务方法增加事务的功能,使用 @Transactional 注解增加事务。@Transactional注解是spring自己的注解。放在 public 方法的上面,表示当前这个方法具有事务,可以给注解的属性赋值,来表示具体的隔离级别、传播行为、异常信息等等。
@Transactional的属性
isolation:用于设置隔离级别,该属性类型为isolation枚举,默认值为 Isolation.DEFUALT。
readOnly:用于设置方法对数据库的操作是否只读的,该属性为boolean,默认值为false。
timeout:用于设置本操作与数据库连接超时时限。单位为妙,类型为int,默认值为-1,即没有时限。
rollbackFor:指定需要回滚的异常类,类型为Class[],默认值为空数组。当然,若只有一个异常类,可以不使用数组。
rollbackForClassName:指定需要回滚的异常类类名。类型为String[],默认值为空数组。当然,若只有一个异常类,可以不使用数组。
noRollbackFor:指定不需要回滚的异常类,类型为Class[],默认值为空数组。当然,若只有一个异常类,可以不使用数组。(与rollbackFor相反)
noRollbackForClassName:指定不需要回滚的异常类类名,类型为Class[],默认值为空数组。当然,若只有一个异常类,可以不使用数组。(与rollbackForClassName相反)
使用注解的步骤:
(1)声明事务管理器对象
<!-- mybatis的事务管理器,id自定义 -->
<!--1、声明spring的事务管理器,id自定义-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--连接的数据库,指定数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean>
(2)开启事务注解驱动,告诉spring,使用注解的方式管理事务。spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务功能。
<!--2、开启事务注解驱动,告诉spring使用注解管理事务,创建带对象
transaction-manager:事务管理器id
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
spring给业务方法加入事务:
在业务方法执行之前,开启事务;在业务方法之后,提交或回滚事务。使用的是 aop的环绕通知。环绕通知由spring完成。
@Around("增加事务功能的业务方法名称")
Object myAround(){
//开启事务,spring开启
try{
<!--业务代码-->
//spring的事务管理 .rollback()
}catch(Exception e){
//spring的事务管理 .rollback()
}
//开启事务,spring开启
}
基于XML配置文件方案(AspectJ框架):适用大型项目 >>【关键代码】
1、大型项目中有很多类,方法,需要大量的配置事务,使用aspectj框架功能,在spring配置文件中声明类,方法需要的事务。这种方式业务方法和事务配置完全分离。
2、实现步骤:都是在xml配置文件中实现的。
(1)要使用的是aspectj框架,加入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
(2)声明事务管理器对象
<!-- mybatis的事务管理器,id自定义 -->
<!--1、声明spring的事务管理器,id自定义-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--连接的数据库,指定数据源-->
<property name="dataSource" ref="myDataSource"/>
</bean>
(3)声明方法需要的事务类型(配置方法的事务属性:隔离级别
、传播行为
、超时
)
(4)配置AOP:指定哪些类需要创建代理对象。
业务代码
总结Spring的事务:
1.管理事务的是事务管理器及其实现类。
2.Spring的事务是一个统一管理模型:
(1)指定要使用的事务管理器的实现类,使用xml配置文件中的<bean ></bean >标签
(2)指定哪些类,哪些方法需要加入事务的功能
(3)指定方法需要的隔离级别,传播行为和超时时间
我们需要告诉Spring我们的项目中类信息,方法的名称,方法的事务传播行为。