Spring管理数据库事务

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 声明式事务

验证实现声明式事务
当程序出现异常时,事务回滚,操作不会被提交
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_52331159/article/details/130516776
今日推荐