Spring 为我们提供了一组事务控制的接口,Spring的事务控制都是基于 AOP 的它即可以使用编程的方式实现,也可以使用配置的方式实现。我们学习的重点是使用配置的方式实现。
环境搭建,导入jar包
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.tedu</groupId> <artifactId>aop</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.6</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.8.RELEASE</version> </dependency> </dependencies> </project>导入命名空间,配置事务控制
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 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/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd"> <context:component-scan base-package="cn.tedu"/> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:druid.properties</value> </list> </property> </bean> <bean class="com.alibaba.druid.pool.DruidDataSource" id="source"> <property name="driverClassName" value="${driverClassName}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> <property name="maxWait" value="${maxWait}"/> <property name="maxActive" value="${maxActive}"/> <property name="initialSize" value="${initialSize}"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg name="dataSource" ref="source"/> </bean> <!--配置事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--注入数据源--> <property name="dataSource" ref="source"/> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 指定方法名称:是业务核心方法 read-only:是否是只读事务。默认false,不只读。 isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。 propagation:指定事务的传播行为。 timeout:指定超时时间。默认值为:-1。永不超时。 rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。 no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,任何异常都回滚。--> <tx:method name="*" read-only="false" propagation="REQUIRED"/> <tx:method name="find*" read-only="true" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <!--配置AOP--> <aop:config> <!--配置切入点表达式--> <aop:pointcut id="pt" expression="execution(* cn.tedu.dao.impl.*.*(..))"/> <!--建立事务的通知和切入点表达式的联系--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/> </aop:config> </beans>修改持久层实现类代码
package cn.tedu.dao.impl; import cn.tedu.dao.IAccountDao; import cn.tedu.entity.Account; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import java.sql.SQLException; import java.util.List; @Repository("dao") public class AccountDaoImpl implements IAccountDao { @Autowired private JdbcTemplate jt; @Override public List<Account> findAll() { List<Account> list = jt.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class)); return list; } @Override public void transfer(String sourceName, String targetName, Double money) { jt.update("update account set balance = balance - ? where name = ?", money,sourceName); int i = 1/0; jt.update("update account set balance = balance + ? where name = ?",money,targetName); } }基于注解的配置方式
添加@Transactional注解 该注解的属性和xml中的属性含义一致。该注解可以出现在接口上,类上和方法上。 出现接口上,表示该接口的所有实现类都有事务支持。 出现在类上,表示类中所有方法有事务支持 出现在方法上,表示方法有事务支持。 以上三个位置的优先级:方法>类>接口在配置文件中开启Spring对注解事务的支持
<!--开启spring对注解事务的支持--> <tx:annotation-driven transaction-manager="transactionManager"/>