使用spring模拟转账,并实现异常事务回滚

1、数据库准备

使用配置类配置数据源、模板、事务回滚

java 复制代码
package cn.edu.aaa.utils;

import java.beans.PropertyVetoException;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.mchange.v2.c3p0.ComboPooledDataSource;
@Configuration
@ComponentScan("cn.edu.aaa")
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement //让事务注释@Transactional起作用
public class MyConfiguration {
	@Value("${driver}")
	private String driver;
	@Value("${url}")
	private String url;
	@Value("${user}")
	private String user;
	@Value("${password}")
	private String password;
	@Bean
//数据源
	public ComboPooledDataSource combopooledDataSource() throws PropertyVetoException {
		ComboPooledDataSource dataSource=new ComboPooledDataSource();
		dataSource.setJdbcUrl(url);
		dataSource.setDriverClass(driver);
		dataSource.setUser("root");
		dataSource.setPassword("root");
		return dataSource;
		
	}
//模板
	@Bean
	public JdbcTemplate jdbcTemplate(@Autowired DataSource dataSource) {
		JdbcTemplate jdbcTemplate=new JdbcTemplate();
		jdbcTemplate.setDataSource(dataSource);
		return jdbcTemplate;
		
	}
//事务处理
	
	  @Bean
	 public PlatformTransactionManager transactionManager(@Autowired DataSource dataSource) {
		  DataSourceTransactionManager transactionManager=new DataSourceTransactionManager();
		  transactionManager.setDataSource(dataSource);
		  return transactionManager;
	}
	 
}

2、创建DAO层

DAO层负责数据库操作。定义了金额操作的方法

(1)定义接口

java 复制代码
package cn.edu.aaa.dao;

public interface AccountDao {
	int addMoney(String aname,int money);
}

(2)接口实现类

java 复制代码
package cn.edu.aaa.dao.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import cn.edu.aaa.dao.AccountDao;
@Repository("AccountDao")//声明这个类是一个Spring管理的bean,并且bean的名称为"AccountDao"。这样,其他Spring组件可以通过"AccountDao"这个名称来引用这个bean。
@Scope("singleton")//声明这个bean的作用域为单例。这意味着在整个Spring容器中,这个bean只有一个实例。
public class AccountDaoImpl implements AccountDao{
	@Autowired //通过@Autowired注解,自动装配一个JdbcTemplate的实例
	private JdbcTemplate jdbcTemplate;
	public int addMoney(String aname, int money) {
		// TODO Auto-generated method stub
		int i=jdbcTemplate.update("update accounts set money=money+? where aname=?",money,aname);//执行一个SQL更新操作,返回更新的记录数
		return i;
	}

}

3、创建Service层

Service层是业务逻辑的核心。定义转账方法

(1)定义接口

java 复制代码
package cn.edu.aaa.biz;

public interface AccountBiz {
	boolean transfer(String aname1,String aname2,Integer money);
}

(2)接口实现类。步骤:

1)转账方金额变少

2)收款方金额变多

3)转账过程中发生异常(事务回滚),输出false,数据表数据不变

java 复制代码
package cn.edu.aaa.biz.impl;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import cn.edu.aaa.biz.AccountBiz;
import cn.edu.aaa.dao.AccountDao;

@Service("AccountBiz")
@Scope("singleton")
public class AccountBizImpl implements AccountBiz{
	@Autowired
	private AccountDao accountDao;
	@Transactional(isolation =Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
	public boolean transfer(String aname1, String aname2, Integer money) {
		// TODO Auto-generated method stub

		try {
			accountDao.addMoney(aname1, (-1)*money);
			//System.out.println(1/0);  //通过开放这句语句,来测试是否对异常处理
			accountDao.addMoney(aname2, money);
			return true;
		}catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//让事务只回滚
			return false;
		}
	}

}

4、测试转账功能

java 复制代码
package cn.edu.aaa.test;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.experimental.theories.suppliers.TestedOn;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import cn.edu.aaa.biz.AccountBiz;
import cn.edu.aaa.utils.MyConfiguration;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes=MyConfiguration.class)//导入配置类

public class AccountBizTest {
	@Autowired

	private AccountBiz accountBiz;
	@Test
	public void test() {
		System.out.println(accountBiz.transfer("superman", "spiderman", 500));
		
	}


}

结果正常,输出true,数据表内容变化

结果异常,输出false,数据表内容不变

5、补充

pom.xml导入依赖

XML 复制代码
<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.edu.aaa</groupId>
  <artifactId>demo2</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-context</artifactId>
  		<version>5.3.23</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.3.23</version>
  	</dependency>
  	
  	<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.3.23</version>
  	</dependency>
  	<dependency>
  		<groupId>com.mchange</groupId>
  		<artifactId>c3p0</artifactId>
  		<version>0.9.5.4</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>8.0.27</version>
  	</dependency>
  	<dependency>
  		<groupId>javax.annotation</groupId>
  		<artifactId>javax.annotation-api</artifactId>
  		<version>1.3.2</version>
  	</dependency>
  	
  	 
  	 
  </dependencies>
  
</project>

目录结构

相关推荐
辛一一1 小时前
neo4j图数据库基本概念和向量使用
数据库·neo4j
熊大如如2 小时前
Java 反射
java·开发语言
巨龙之路2 小时前
什么是时序数据库?
数据库·时序数据库
蔡蓝2 小时前
binlog日志以及MySQL的数据同步
数据库·mysql
猿来入此小猿2 小时前
基于SSM实现的健身房系统功能实现十六
java·毕业设计·ssm·毕业源码·免费学习·猿来入此·健身平台
goTsHgo3 小时前
Spring Boot 自动装配原理详解
java·spring boot
卑微的Coder3 小时前
JMeter同步定时器 模拟多用户并发访问场景
java·jmeter·压力测试
是店小二呀3 小时前
【金仓数据库征文】金融行业中的国产化数据库替代应用实践
数据库·金融·数据库平替用金仓·金仓数据库2025征文
pjx9873 小时前
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
java·spring cloud·微服务·eureka
炒空心菜菜3 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark