Spring中的事务控制。
PlatformTransactionManager
Spring的事务管理器,提供了常用的操作事务的方法,我们在开发中都使用它的实现类。
1 | //获取事务状态信息 |
真正管理事务的对象
1 | org。springframework。jdbc。datasource。DataSourceTransactionManager//使用Spring JDBC或iBatis进行持久化数据时使用 |
TransactionDefinition
事务的定义信息对象,有如下方法:
-
String getName()
: 获取事务对象名称 -
int getIsolationLevel()
: 获取事务隔离级别,设置两个事务之间的数据可见性ISOLATION_DEFAULT
: Spring事务管理的的默认级别,使用数据库默认的事务隔离级别ISOLATION_READ_UNCOMMITTED
: 读未提交ISOLATION_READ_COMMITTED
: 读已提交,解决脏读问题ISOLATION_REPEATABLE_READ
: 是否读取其他事务提交修改后的数据,解决不可重复读问题ISOLATION_SERIALIZABLE
: 串行化,是否读取其他事务提交添加后的数据,解决幻影读问题
-
int getPropagationBehavior()
: 获取事务传播行为,设置新事务是否事务以及是否使用当前事务通常使用的是前两种
REQUIRED
和SUPPORTS
,事务传播行为如下:REQUIRED
: Spring默认事务传播行为。 若当前没有事务,就新建一个事务;若当前已经存在一个事务中,加入到这个事务中。增删改查操作均可用SUPPORTS
: 若当前没有事务,就不使用事务;若当前已经存在一个事务中,加入到这个事务中。查询操作可用MANDATORY
: 使用当前的事务,若当前没有事务,就抛出异常REQUERS_NEW
: 新建事务,若当前在事务中,把当前事务挂起NOT_SUPPORTED
: 以非事务方式执行操作,若当前存在事务,就把当前事务挂起NEVER
:以非事务方式运行,若当前存在事务,抛出异常NESTED
:若当前存在事务,则在嵌套事务内执行;若当前没有事务,则执行REQUIRED类似的操作
-
int getTimeout()
: 获取事务超时时间默认值是-1,没有超时限制。如果有以秒为单位进行设置
-
boolean isReadOnly()
: 获取事务是否只读建议查询时设置为只读
TransactionStatus
事务状态信息对象,提供操作事务状态的方法如下:
void flush()
: 刷新事务boolean hasSavepoint()
: 查询是否存在存储点,事务的一步,按步提交boolean isCompleted()
: 查询事务是否完成boolean isNewTransaction()
: 查询是否是新事务boolean isRollbackOnly()
: 查询事务是否回滚void setRollbackOnly()
: 设置事务回滚
基于XML的声明式事务配置
-
配置事务管理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<!--新的约束-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans> -
配置事务的通知,此时需要导入事务的约束
1
<tx:advice id="txAdvice" transaction-manager="transactionManager"></tx:advice>
-
配置AOP中切入点表达式
-
建立事务通知和切入点表达式的对应关系
1
2
3
4
5
6<!--配置切入点表达式-->
<aop:config>
<aop:pointcut id="pt1" expression="execution(* com.ztygalaxy.service.impl.*.*(..))"/>
<!--配置切入点表达式和事务通知的对应关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config> -
配置事务的属性,在事务的通知tx:advice标签内部配置。
- isolation: 用于指定事务的隔离级别,默认值是DEFAULT,表示使用数据库的默认隔离级别。
- no-rollback-for: 用于指定一个异常,当产生该异常时,事务不回滚。没有默认值,表示任何异常都回滚。
- propagation: 用于指定事务的传播行为,默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
- read-only: 用于指定事务是否只读,只有查询方法才能设置为true,默认值是false,表示读写。
- rollback-for: 用于指定一个异常,当产生一个异常时,事务回滚,产生其他异常时不回滚。没有默认值,表示任何异常值都回滚。
- timeout: 用于指定事务的超时时间,默认值是-1,表示永不超时,如果制定了数值,以秒为单位。
1
2
3
4
5
6
7
8
9<!--配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--通配符-->
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<!--查询方法-->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
基于注解的声明式事务控制
-
配置事务管理器
-
开启spring对注解事务的支持
1
2
3
4
5
6//Dao中取消JDBCSupport
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {
private JdbcTemplate jdbcTemplate;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.ztygalaxy"></context:component-scan>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--spring中基于声明式事务配置-->
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启spring对注解事务的支持-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans> -
在需要事务支持的地方使用
@Transaction
注解1
2
3
4
5
6
7
8
9
10
public class AccountServiceImpl implements IAccountService {}
//或者对整个类定义后,对单个方法修改
public class AccountServiceImpl implements IAccountService {
public void transfer(String sourceName, String targetName, Float money) {}
}
基于纯注解的事务配置
-
事务控制配置类
TransactionConfig
1
2
3
4
5
6
7public class TransactionConfig {
//用于创建事务管理器对象
public PlatformTransactionManager createTransactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
} -
JDBC配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public class JdbcConfig {
private String driver;
private String url;
private String username;
private String password;
//创建JdbcTemplate对象
public JdbcTemplate createJdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
//创建数据源对象
public DataSource createDataSource(){
DriverManagerDataSource ds=new DriverManagerDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}
} -
JDBC配置文件
1
2
3
4jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root -
总配置类
1
2
3
4
5
6
7
public class SpringConfiguration {
} -
测试类
1
2
3
4
5
6
7
8
9
10
public class AccountService {
private IAccountService as;
public void transfer(){
as.transfer("bbb","ccc",234f);
}
}
Spring编程式事务控制
Spring的编程式事务控制不能实现解耦,反而使耦合更加严重了,因此不推荐使用。