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

1、数据库准备

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

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)定义接口

package cn.edu.aaa.dao;

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

(2)接口实现类

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)定义接口

package cn.edu.aaa.biz;

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

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

1)转账方金额变少

2)收款方金额变多

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

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、测试转账功能 

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导入依赖

<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. spring事务异常如何解决

    2024-04-09 17:48:01       40 阅读
  2. Spring事务规则,是否只读,超时时间,事务失效

    2024-04-09 17:48:01       82 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-09 17:48:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-09 17:48:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-09 17:48:01       87 阅读
  4. Python语言-面向对象

    2024-04-09 17:48:01       96 阅读

热门阅读

  1. Python入门:轻松学习,编程不再难

    2024-04-09 17:48:01       36 阅读
  2. 云智前端面试题

    2024-04-09 17:48:01       32 阅读
  3. 服务器硬件基础知识解析

    2024-04-09 17:48:01       31 阅读
  4. Vue.nextTick() 使用场景及实现原理

    2024-04-09 17:48:01       38 阅读
  5. DockerFile定制镜像

    2024-04-09 17:48:01       32 阅读
  6. Vue3 · 小白学习全局 API:常规

    2024-04-09 17:48:01       38 阅读
  7. 面试前必看,仅供参考

    2024-04-09 17:48:01       34 阅读
  8. 蓝桥杯算法题:蓝桥公园

    2024-04-09 17:48:01       38 阅读