一:spring使用注解的方式进行事务声明

1.spring的声明式事务:

用jdbc的事务管理器:DataSourceTransactionManager

首先在applicationContext.xml 文件中进行配置

spring手动管理事务 连接数不释放 spring进行事务管理_spring手动管理事务 连接数不释放

这里的property中的name就是数据库的bean,ref对应的是applicationContext.xml 文件中的数据库bean定义的id,也就是将数据源于事务进行绑定,

而启用事务注解中的transaction-manager值必须是trasactionManager,若配置的事务管理器的ID为trasactionManager,nametransaction-manager可以不写

然后在service的实现层中添加事务注解:在对应的service实现了的方法上添加@Transactional注解。

spring手动管理事务 连接数不释放 spring进行事务管理_自定义异常_02

2.事务的传播行为:

在service服务层中存在两个方法,而这两个方法都有各自的事务声明,如果其中一个方法调用另一个方法,被调用的方法使用调用者的事务,还是用自己的事务呢?此时就涉及到了事务的传播了。

spring的七个事务传播属性:

PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
 PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
 PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
 PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
 PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
 PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,

那么在建一个事务方法checkout,也对此方法进行事务管理,但此时的方法调用了上一个事务方法purchase:

spring手动管理事务 连接数不释放 spring进行事务管理_自定义异常_03

此时不指定事务的传播行为,默认行为是REQUIRED,那么purchase事务方法到底是用自己的事务呢?还是用checkout的事务呢?

结果是purchase方法用的是checkout的事务,也就是说当purchase方法第一次执行成功了,第二次执行失败了,那么结果会回滚到checkout最原始的状态,第一次也默认是失败了

spring手动管理事务 连接数不释放 spring进行事务管理_数据库_04

当指定传播行为(传播行为的指定要在被调用方法上进行指定,也就是在purchase方法上进行指定)为PROPAGATION_REQUIRES_NEW时,结果如何呢?

spring手动管理事务 连接数不释放 spring进行事务管理_java_05

次传播行为造成的结果就是,当purchase方法第一次执行成功了,第二次执行失败了,只会回滚到purchase第二次执行开始的状态,而checkout方法不会进行回滚,purchase方法第一次成功了就是成功了。

spring手动管理事务 连接数不释放 spring进行事务管理_spring手动管理事务 连接数不释放_06

3.事务的其他属性(事务的隔离级别&只读&过期)

spring手动管理事务 连接数不释放 spring进行事务管理_数据库_07

对于所抛异常的类型我们可以自己进行创建,创建个类名称自己定义,将此类继承RuntimeException异常类,在自定义异常类中创建构造器即可,无需对方法中添加其他任何代码,我们只是为了想要得到自己定义的异常名称,那么抛异常的时候就可以这样写了,例如自定义异常UserAccountException,就可以这样抛异常

throw new UserAccountException("自定义异常内容");