1.什么是事务
事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性;就是多个步骤同一事务后,确保了完整性
2.实现事务的两种方式
编程式事务管理:
将事务管理代码嵌入到业务方法中来控制事务的提交和回滚,在编程式管理事务中,必须在每个事务操作中包含额外的事务管理代码。
声明式事务管理(推荐):
大多数情况下比编程式事务管理更好用,它将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理,Spring声明式事务管理建立在AOP基础之上,是一个典型的横切关注点,通过环绕增强来实现,其原理是对方法前后进行拦截,然后在目标方法开始之前创建或加入一个事务,在执行完毕之后根据执行情况提交或回滚事务,其模型如下:
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
try {
//开启事务
return joinPoint.proceed();
//提交事务
} catch (Throwable e) {
//回滚事务
throw e;
}finally {
//释放资源
}
}
3详述声明式过程@Transactional
步骤:
如何实现声明式事务
1、添加spring-aspects-4.3.10.RELEASE.jar包
2、在Spring配置文件中添加如下配置
3、在Service层public方法上添加事务注解——@Transactional
此时数量和剩余价格就在同一个事务中了
4.@Transactional的几个属性
1、timeout:设置一个事务所允许执行的最长时长(单位:秒),如果超过该时长且事务还没有完成,则自动回滚事务且出现org.springframework.transaction.TransactionTimedOutException异常,如下代码:因此事务自动回滚,书籍表库存递减操作无效,程序出现org.springframework.transaction.TransactionTimedOutException异常!
2.readOnly:事务只读,指对事务性资源进行只读操作。所谓事务性资源就是指那些被事务管理的资源,比如数据源、 JMS 资源,以及自定义的事务性资源等等。如果确定只对事务性资源进行只读操作,那么可以将事务标志为只读的,以提高事务处理的性能。在 TransactionDefinition 中以 boolean 类型来表示该事务是否只读。由于只读的优化措施是在一个事务启动时由后端数据库实施的, 因此,只有对于那些具有可能启动一个新事务的传播行为(PROPAGATION_REQUIRES_NEW、PROPAGATION_REQUIRED、 ROPAGATION_NESTED)的方法来说,将事务声明为只读才有意义。
下面代码对数据进行了修改,不是只读
@Transactional注解中添加了readOnly=true,但@Transactional注解修饰的方法涉及数据的修改,因此抛出如下异常:
Caused by: java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
5.事务@Transactional的属性(事务回滚条件)
@Transactional注解属性:
rollbackFor和rollbackForClassName:指定对哪些异常回滚事务。默认情况下,如果在事务中抛出了运行时异常(继承自RuntimeException异常类),则回滚事务;如果没有抛出任何异常,或者抛出了检查时异常,则依然提交事务。这种处理方式是大多数开发者希望的处理方式,也是 EJB 中的默认处理方式;但可以根据需要人为控制事务在抛出某些运行时异常时仍然提交事务,或者在抛出某些检查时异常时回滚事务。
例子:
1.书籍表中有50本书籍,每本书10元,一个人钱包有1元,欲买50本,则该行代码抛出MoneyException异常,但由于该异常为运行时异常,所以回滚事务,即左边图片“bookDao.update(bookId, count);”行代码执行失效!
Monexpection运行时异常类:
2.书籍表中有50本书籍,每本书10元,一个人钱包有1元,欲买50本,则该行代码抛出MoneyException异常,尽管该异常为检查时异常,但由于@Transactional注解中添加了rollbackFor=MoneyException.class,所以回滚事务,即左边图片“bookDao.update(bookId, count);”行代码执行失效!
2.MoneyExpection类,检查式异常