spring的事务处理
mysql开始,提出了事务的概念。事务是指一组sql语句的集合,集合中有多条sql语句,可能是insert,update,select,delete,我们希望这些多个sql语句都能成功,或者失败,这些sql语句的执行是一致的,作为一个整体执行。
当我们的操作涉及到多个表,或者是多个sql语句的insert、update、delete。需要保证这些语句都是成功才能完成我们的功能,或者都失败,保证操作是符合要求的。
列如a转账给b,那么涉及到a的sql操作和b的sql操作必须同时成功,否则必须同时失败
在java代码中写程序,控制事务,此时事务应该放在那里?
service类的业务方法上,因为业务方法会调用多个dao方法,执行多个sql语句。
jdbc访问数据库,处理事务 Connection conn;conn.commit();conn.rollback();
mybatis访问数据库,处理事务, SqlSession.commit();SqlSession.rollback();
hibernate访问数据库,处理事务, Session.commit();Session.rollback();
1)不同的数据库访问技术,处理事务的对象,方法不同
需要了解不同数据库访问技术使用事务的原理
2)掌握多种数据库中事务的处理逻辑。什么时候提交事务,什么时候回滚事务
3)处理事务的多种方法
总结:多种数据库的访问技术,有不同的事务处理的机制、对象、方法。
spring提供一种处理事务的统一模型,能使用统一步骤、方式完成多种不同数据库访问技术的事务处理
使用spring的事务处理机制,可以完成mybatis访问数据库的事务处理。
使用spring的事务处理机制,可以完成hibernate访问数据库的事务处理。
spring处理事务的模型,使用的步骤都是固定的。把事务使用的信息提供给spring就可以了
1) 事务内部提交,回滚事务。使用的事务管理器对象,代替你完成commit,rollback
事务管理器是一个接口和它的众多实现类。
接口:PlatformTransactionManager,定义了事务的重要方法commit,rollback
实现类:spring把每一种数据库访问技术对应的事务处理类都创建好了。
mybatis访问数据库—spring创建好的事DateSourceTransactionManager
hibernate访问数据库—spring创建的是HibernateTransactionManager
怎么使用:你需要告诉spring你用的是哪种数据库访问技术,如何告诉spring?
生命数据库访问技术对应的事务管理器实现类,在spring的配置文件中使用
声明就可以了
2) 你的业务方法需要什么样的业务,说明需要事务的类型。
说明方法需要的事务:
2.1) 事务的隔离级别:有4个值
DEFAULT:采用DB默认的事务隔离级别。MySql的默认为REPEATABLE_READ;Oracle默认为READ_COMMITTED
2.2) 事务的超时时间:表示一个方法的最长的执行时间,如果方法执行超过了时间,事务就会回滚。
单位是秒,整数值,默认是-1,意思是没有超时时间,如果没有执行完就一直执行,一般不配置。
关键字是TIMEOUT_DEFAULT
2.3) 事务的传播行为:控制业务方法是不是有事务的,是什么样的事务的。
7个传播行为:表示你的业务方法调用时,事务在方法之间是如何使用的
3) 事务提交事务,回滚事务的时机
3.1) 当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring在方法执行后提交事务。
3.2) 当你的业务方法抛出运行时异常或ERROR时,spring执行回滚,调用事务管理器的rollback
运行时异常:RuntimeException和它的子类都是运行时异常,例如NullPointException,NumberFormatException
3.3) 当你的业务方法抛出非运行时异常,主要是受查异常时,提交事务
受查异常:在你写代码中,必须处理的异常。例如IOException,SQLException
总结spring的事务
1.管理事务的是 事务管理器和它的实现类
2.spring的事务是一个统一模型
1)指定要使用的事务管理器实现类,使用
2)指定哪些类,哪些方法需要加入事务的功能
3)指定方法需要的隔离级别、传播行为、超时
你需要告诉spring,你的项目中类信息,方法的名称,方法的事务传播行为。
spring框架自己用aop实现给业务方法增加事务的功能,使用 @Transacitonal 注解增加事务。
@Transacitonal注解是spring框架自己的注解,放在publi方法的上面,表示当前方法具有事务
可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等。
@Transactional的所有可选属性如下:
1.propagation:用于设置事务的传播属性。该属性类型为Propagation,默认值为Propagation.REQUIRED
2.isolation:用于设置事务的隔离级别。该属性类型为Isolation,默认值为Isolation.DEFAULT
3.readOnly:用于设置该方法对数据库的操作是否是只读的。该属性类型为boolean,默认值为false,如果事务中所有的方法只需要进行查询操作,可设置为true,可能能够提高数据库的访问速度。
4.timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为int,默认值为-1,即没有时限。
5.rollbackFor:指定需要回滚的异常类。类型为Class[] 默认值为空数组。当然,若只有一个异常类,可以不是用数组。
6.rollbackForClassName:注定需要回滚的异常类类名。类型为String[],默认值为空数组,只有一个异常类时,不需要使用空数组。
7.noRollbackFor:指定不需要回滚的异常类。类型为Class[],默认值为空数组。只有一个异常类时,不需要使用数组。
8.noRollbackForClassName:指定不需要回滚的异常类类名。类型为String[],默认值为空数组。只有一个异常类时,不需要使用数组。
1.需要声明事务管理器对象
(这是mybatis的事务管理器)
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="数据源"/>
bean>
2.开启事务注解驱动,告诉spring框架,我们要使用注解的方式管理事务
<tx:annotation-driven transaction-manager="transactionManager"/>
spring使用aop机制,创建@Transacitonal所在的类代理对象,给方法加入事务的功能。
spring给业务方法加入事务:
在你的业务方法执行之前,先开启事务,在业务方法之后提交或回滚事务,使用aop的环绕通知(这是spring替你完成的,你不用写,原理如下)
@Around("你要增加的事务功能的业务方法名称")
Object myAround(){
开启事务,spring替你开启
try{
buy(1001,10);
spring的事务管理器.commit();
}catch(Exception ex){
spring的事务管理器.rollback();
}
}
3.在你的方法上面加入@Transactional
/*
* rollbackFor:表示发生指定的异常一定回滚
* 处理逻辑是:
* 1)spring框架会首先检查方法抛出的异常是不是在rollbackFor的属性值中
* 如果异常在rollbackFor列表中,那么一定回滚
* 2)如果你抛出的异常不在rollbackFor列表中,spring会判断异常是不是RuntimeException,
* 如果是,一定回滚
* */
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,
readOnly = false,
rollbackFor = {
NullPointerException.class
}
)
@Override
public void buy(int gid, int nums) {
}
适合大型项目,有很多的类、方法,需要大量的配置事务,使用aspectj框架功能,在spring配置文件中声明类,方法需要的事务。这种方式业务方法和事务配置完全锋利
实现步骤:都在是xml配置文件中实现。
1)要使用的是aspectj框架,需要加入依赖
(如何使用aspectj框架可参考spring笔记中的3.6AOP实现)
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>5.2.5.RELEASEversion>
dependency>
2)声明事务管理器对象
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="数据源"/>
bean>
3)声明方法需要的事务类型(配置方法的事务属性【隔离级别isolation,传播行为propagation,超时timeout】)
spring框架在识别事务方法的过程中,存在优先级,完整方法名>部分方法名+通配符>通配符
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="myDataSource"/>
bean>
<tx:advice id="myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="buy" propagation="REQUIRED" isolation="DEFAULT" timeout="-1"
rollback-for="java.lang.NullPointerException"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="modify*" />
<tx:method name="remove*"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
tx:attributes>
tx:advice>
4)配置aop:指定哪些类需要创建代理
<aop:config>
<aop:pointcut id="servicePt" expression="execution(* *..service..*.*(..))"/>
<aop:advisor advice-ref="myAdvice" pointcut-ref="servicePt"/>
aop:config>