事务添加的位置
一般事务添加到三层结构(Web层,Service层,Dao层)中的Service层(业务逻辑层)中。
Spring进行事务管理操作的方式
- 编程式事务管理(不常用,不方便,通过try,catch方法,会造成代码臃肿)
- 声明式事务管理(常用),包括注解式(常用)和XML配置文件式
在Spring中进行声明式事务管理时,底层使用的是AOP原理
Spring事务管理API
Spring提供了一个接口,代表事务管理器。这个接口针对不同的框架提供不同的实现类。这个接口是PlatformTransactionManager
注解方式实现声明式事务管理
- 在Spring配置文件中配置事务管理器(就是创建上面说的接口的实现类的对象)
- 在配置文件中开启事务注解:首先在配置文件中引入名称空间tx,然后利用tx:annotation-driven标签开启事务注解
- 在service类上(或service类里面的方法上)添加事务注解@Transactional。如果加在类上,这个类中所有的方法都添加事务;如果添加到方法上,仅仅为这个方法添加事务
事务的传播行为
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
事务方法:对数据库表数据进行变化的操作(增删改)。
传播行为:一个有(无)事务方法调用一个无(有)事务方法应该怎么做(或者两个都有事务)(个人认为这个定义可能不如第一句靠谱)
Spring中事务传播行为有7种(前两个用的最多):
- REQUIRED:如果有事务在运行,当前方法就在这个事务内运行,否则就启动一个新事务,并在自己的事务内运行(默认)
- REQUIRED_NEW:当前方法必须启动新事务,并在它自己的事务内运行,如果有事务在运行,应该将其挂起
- SUPPORTS:如果有事务在运行,当前方法就在这个事务内运行,否则它可以不运行在事务中。
- NOT_SUPPORTED:当前方法不应该运行在事务中,如果有运行的事务,将其挂起
- MANDATORY:当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常
- NEVER:当前方法不应该运行在事务中,如果有运行的事务就抛出异常
- NESTED:如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新事务,并在它自己的事务内运行。
事务的隔离级别
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
READ UNCOMMITTED(读未提交) | 有 | 有 | 有 |
READ COMMITTED(读已提交) | 无 | 有 | 有 |
REPEATABLE READ(可重复读) | 无 | 无 | 有 |
SERIALIZABLE(串行化) | 无 | 无 | 无 |
MySQL中默认是REPEATABLE READ
声明式事务管理的参数配置
在service类上添加注解Transactional,在这个注解里可以配置事务相关参数
- propagation:事务的传播行为,即多事务方法之间进行调用,这个过程中事务是如何进行管理的。
- isolation:事务的隔离级别
- timeout:超时时间:事务需要在一定时间内进行提交,如果不提交就进行回滚。默认值为-1,表示不超时。设置时间以秒为单位计算。
- readOnly:是否只读,默认为false,即可以增删改查。如果改成true就只能查询
- rollbackFor:回滚:设置出现哪些异常进行事务回滚
- noRollbackFor:不回滚:设置出现哪些异常不进行事务回滚
XML声明式事务管理
1.配置事务管理器
2.利用tx:advice标签配置通知,然后在里面用tx:attributes标签配置事务参数;接着在参数标签里面利用tx:method标签指定哪种规则的方法上面添加事务。
3.配置切入点和切面,具体过程同AOP中所述。
完全注解开发
首先创建配置类,使用@Configuration声明它是配置类,使用@ComponentScan(basePackage="")开启组件扫描,使用@EnableTransactionManager开启事务。
然后在类中创建数据库连接池:首先创建一个返回DruidDataSource的方法,在其上加入@Bean注解,然后在类中创建返回值对象,使用对象中的set方法配置之前在配置文件中配置的属性。
创建JDBC模板对象,过程同上。在注入DataSource时可以将方法的参数设为DataSource,然后直接注入参数。这样做的含义是:因为之前已经创建了连接池,在容器中已经存在了DataSource对象,这样写表示根据其类型到容器中找到对象注入。
创建事务管理器,过程同上。