Spring编程式事务和声明式事务的验证
- 1、工程目录
- pom.xml
- 2、在resources目录创建配置文件
- applicationContext_1.xml
- applicationContext_2.xml
- applicationContext_3.xml
- jdbc.properties
- 3、创建数据表account
- account
- 4、创建dao类
- 5、创建service类
- 6、创建测试类
- 7、实验结果图
- 1 编程式事务
- 2 声明式事务
1、工程目录
pom.xml
<?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>org.example</groupId>
<artifactId>chapter10</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>6</source>
<target>6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>mchange-commons-java</artifactId>
<version>0.2.19</version>
</dependency>
</dependencies>
</project>
2、在resources目录创建配置文件
applicationContext_1.xml
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 引入外部 properties 文件 -->
<context:property-placeholder
location="classpath:jdbc.properties" />
<!-- 注册数据源 -->
<bean name="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--注册JdbcTemplate类 -->
<bean name="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注册事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注册TransactionTemplate类 -->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean name="accountDao" class="com.qfedu.dao.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean name="accountService"
class="com.qfedu.service.AccountServiceImpl01">
<property name="accountDao" ref="accountDao"></property>
<property name="transactionTemplate"
ref="transactionTemplate"></property>
</bean>
</beans>
applicationContext_2.xml
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 引入外部 properties 文件 -->
<context:property-placeholder
location="classpath:jdbc.properties" />
<!-- 注册数据源 -->
<bean name="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 注册JdbcTemplate类 -->
<bean name="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注册事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="accountDao" class="com.qfedu.dao.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean name="accountService"
class="com.qfedu.service.AccountServiceImpl02">
<property name="accountDao" ref="accountDao" />
</bean>
<!-- 事务通知 -->
<tx:advice id="txAdvice"
transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="transfer*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- AOP配置 -->
<aop:config>
<aop:pointcut id="txPointCut"
expression="execution(* com..service..*.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="txPointCut" />
</aop:config>
</beans>
applicationContext_3.xml
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 引入外部 properties 文件 -->
<context:property-placeholder
location="classpath:jdbc.properties" />
<!-- 注册数据源 -->
<bean name="dataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}" />
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
<property name="user" value="${jdbc.user}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 注册JdbcTemplate类 -->
<bean name="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 注册事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean name="accountDao" class="com.qfedu.dao.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean name="accountService"
class="com.qfedu.service.AccountServiceImpl03">
<property name="accountDao" ref="accountDao" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
jdbc.properties
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/chapter10
jdbc.user=root
jdbc.password=123456
3、创建数据表account
account
4、创建dao类
AccountDao
package com.qfedu.dao;
public interface AccountDao {
void increaseMoney(Integer id, Double money);
void decreaseMoney(Integer id, Double money);
}
AccountDaoImpl
package com.qfedu.dao;
import org.springframework.jdbc.core.JdbcTemplate;
public class AccountDaoImpl implements AccountDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void increaseMoney(Integer id, Double money) {
jdbcTemplate.update("update account set money = money + ? " + "where id = ? ;", money, id);
}
@Override
public void decreaseMoney(Integer id, Double money) {
jdbcTemplate.update("update account set money = money - ? " + "where id = ? ;", money, id);
}
}
5、创建service类
AccountService
package com.qfedu.service;
public interface AccountService {
void transfer(Integer from, Integer to, Double money);
}
注意
修改AccountServiceImpl
①实现转账业务
accountDao.decreaseMoney(from, money);
accountDao.increaseMoney(to, money);
②验证实现了事务
当出现异常时(此处异常为分母为0),事务回滚,转账操作不会被提交
accountDao.decreaseMoney(from, money);
int num = 1 / 0;
accountDao.increaseMoney(to, money);
①和②二者保存一个,使用其中一个时,注释掉另一个,三个实现类都是这样。
AccountServiceImpl01
package com.qfedu.service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.*;
import com.qfedu.dao.AccountDao;
public class AccountServiceImpl01 implements AccountService {
private AccountDao accountDao;
// 事务管理类
private TransactionTemplate transactionTemplate;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
// final 声明方法,Java 里用 final 修饰符去修饰一个方法的唯一正确用途就是表达:
// 这个方法原本是一个虚方法,现在通过 final 来声明这个方法不允许在派生类中进一步被覆写(override)。
@Override
public void transfer(final Integer from, final Integer to, final Double money) {
// 调用TransactionTemplate类对象执行execute()方法
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
// 需要在事务环境中执行的代码
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// accountDao.decreaseMoney(from, money);
// accountDao.increaseMoney(to, money);
accountDao.decreaseMoney(from, money);
int num = 1 / 0;
accountDao.increaseMoney(to, money);
}
});
}
}
AccountServiceImpl02
package com.qfedu.service;
import com.qfedu.dao.AccountDao;
public class AccountServiceImpl02 implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(Integer from, Integer to, Double money) {
accountDao.decreaseMoney(from, money);
accountDao.increaseMoney(to, money);
// accountDao.decreaseMoney(from,money);
// int num = 1/0;
// accountDao.increaseMoney(to,money);
}
}
AccountServiceImpl03
package com.qfedu.service;
import org.springframework.transaction.annotation.Transactional;
import com.qfedu.dao.AccountDao;
@Transactional
public class AccountServiceImpl03 implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(Integer from, Integer to, Double money) {
// accountDao.decreaseMoney(from, money);
// accountDao.increaseMoney(to, money);
accountDao.decreaseMoney(from, money);
int num = 1 / 0;
accountDao.increaseMoney(to, money);
}
}
6、创建测试类
TestAccountService01
package com.qfedu.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.qfedu.service.AccountService;
public class TestAccountService01 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_1.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);
accountService.transfer(1, 2, 1000.0);
}
}
TestAccountService02
package com.qfedu.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.qfedu.service.AccountService;
public class TestAccountService02 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_2.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);
accountService.transfer(1, 2, 1000.0);
}
}
TestAccountService03
package com.qfedu.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.qfedu.service.AccountService;
public class TestAccountService03 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext_3.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);
accountService.transfer(1, 2, 1000.0);
}
}
7、实验结果图
1 编程式事务
验证实现编程式事务
当程序出现异常时,事务回滚,操作不会被提交
2 声明式事务
验证实现声明式事务
当程序出现异常时,事务回滚,操作不会被提交