目录
Spring声明式基于AOP 实现,是通过配置注解 或xml来管理事务,而不需要在业务代码中像编程式事务那样管理代码。
特性 | 编程式事务 | 声明式事务 |
---|---|---|
代码侵入性 | 强,事务代码与业务代码混合 | 弱,通过配置或注解,代码几乎无侵入 |
控制粒度 | 细粒度,可以精确控制事务边界 | 粗粒度,通常作用于方法级别 |
灵活性 | 高,可以根据条件动态控制事务 | 相对较低,配置固定,但可通过条件表达式等增强 |
可维护性 | 低,事务代码分散在业务代码中 | 高,事务配置集中管理 |
实现方式 | 编写代码,使用PlatformTransactionManager 或TransactionTemplate |
使用注解(如@Transactional )或XML配置 |
底层技术 | 直接使用事务API | 基于Spring AOP和代理机制 |
声明式事务的实现方式
声明式事务可以通过XML或注解配置,也可以混合使用。
XML配置
xml配置声明式有三个步骤:
- 配置事务管理器
- 配置事务通知
- 配置AOP
配置事务管理器:
XML<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
配置事务通知:
配置说明:
事务通知(tx:advice)
id="txAdvice"
:事务通知的唯一标识transaction-manager="transactionManager"
:关联前面定义的事务管理器事务属性(tx:attributes) 通过
<tx:method>
定义不同方法的事务规则,支持通配符匹配方法名:
name
:方法名匹配规则(如save*
匹配所有以 save 开头的方法)propagation
:事务传播行为(核心属性)
REQUIRED
:默认值,当前无事务则新建,有则加入REQUIRES_NEW
:强制新建事务,暂停当前事务(若存在)SUPPORTS
:支持事务,无事务则非事务执行isolation
:事务隔离级别(默认DEFAULT
,使用数据库默认)read-only
:是否只读(查询方法设为true
,优化性能)rollback-for
:指定需要回滚的异常(默认仅回滚 RuntimeException)timeout
:事务超时时间(-1 表示无限制)
XML<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*"/> <tx:method name="update*"/> <tx:method name="delete*"/> <tx:method name="insert*"/> <tx:method name="transfer*"/> </tx:attributes> </tx:advice>
配置AOP:
XML<aop:config> <aop:pointcut expression="execution(* com.cc.service.*.*(..))" id="pc"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"/> </aop:config>
然后编写方法,注意方法名要和配置的方法名对应:
java
public void update2(){
userDao.updateUsernameById(1,"ng");
int i = 1/0;
}

这样调用该方法,抛异常时就会自动回滚。
配置类配置
首先写一个java配置类来代替spring的配置文件,里面包含了定义事务管理器和mybatis配置:
java
@Configuration
@ComponentScan("com.cc")
@EnableTransactionManagement
@MapperScan("com.cc.dao")
public class JavaConfig {
@Bean
DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/shop-user");
ds.setUsername("root");
ds.setPassword("123456");
return ds;
}
@Bean
PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(dataSource());
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
return sessionFactory.getObject();
}
}
接着在业务方法上面加上注解@Transactional,
@Transactional public void tr(){ userDao.updateUsernameById(1,"ng1n"); int i = 1/0; }
然后用一个main方法区调用,发现事务自动回滚:
java
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
UserService2 bean = context.getBean(UserService2.class);
bean.tr();
}
混合配置
混合配置使用xml+注解的方式,无需使用配置类
XML中的配置:
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/shop-user"/> <property name="username" value="root"/> <property name="password" value="123456"/> </bean> <bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory"> <property name="dataSource" ref="dataSource"></property> </bean> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> \<!-- 开启注解式事务支持--\> <tx:annotation-driven/>
后面直接使用@Transactional注解即可。