Spring练习六,模拟转账过程中发生异常,使用spring来进行事物管理(全注解的方式实现))

1.转账的描述

转账的过程有转出和收到,只有转出并且收到了才是一个完成的事物.所以只要转账过程中有一方发生错误,事物就必须回滚

2.在数据库中创建表

create table account(
id number primary key,
name varchar2(20),
balance number
);
insert into account values(1,'tom',10000.00);
insert into account values(2,'jerry',10000.00);
commit;

3.需要使用到的jar包

4.创建实体类

package db.bean;

public class Account {
	private long id;
	private String name;
	private double balance;
	public Account() {
		// TODO Auto-generated constructor stub
	}
	
	public Account(long id, String name, double balance) {
		super();
		this.id = id;
		this.name = name;
		this.balance = balance;
	}

	public long getId() {
	return id;
	}
	public void setId(long id) {
	this.id = id;
	}
	public String getName() {
	return name;
	}
	
	public void setName(String name) {
	this.name = name;
	}
	public double getBalance() {
	return balance;
	}
	public void setBalance(double balance) {
	this.balance = balance;
	}
	@Override
	public String toString() {
	return "Account [id=" + id + ", name=" + name + ", balance=" + balance + "]";
	}
}

5.创建一个db.properties文件用来保存创建DataSource对象的信息

user,password和自己数据库保存相同

driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
user=cyg
password=cyg
initSize=3
maxWait=3000

6.创建一个DBAppConfig类用来产生DataSource对象,jdbcTemplate对象和事物管理的对象

package db.config;

import javax.sql.DataSource;
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.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.alibaba.druid.pool.DruidDataSource;

//不用xml的配置,用java来进行配置要注释@Configuration表示这是一个spring配置类
@Configuration
//扫描包
@ComponentScan(basePackages= {"db.dao","db.service"})
//读取db.properties文件
@PropertySource(value = "classpath:db.properties")
//在转账的过程中可能会发生异常所以要启动事物管理
@EnableTransactionManagement

public class DBAppConfig {
	@Value("${url}")
	private String url;
	@Value("${driver}")
	private String driver;
	@Value("${user}")
	private String user;
	@Value("${password}")
	private String password;
	@Value("${initSize}")
	private int initSize;
	@Value("${maxWait}")
	private long maxWait;
	
	//事物管理
	@Bean
	public DataSourceTransactionManager transactionManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}
	
	
	//创建jdbcTemplate对象
	@Bean(name = "jdbcTemplate")
	public JdbcTemplate setDataSource(DataSource dataSource) {
		//return new JdbcTemplate(dataSource);
		return new JdbcTemplate(createDataSource());
	}
	//创建DataSource对象
	@Bean(name = "dataSource")
	public DataSource createDataSource() {
		DruidDataSource ds = new DruidDataSource();
		ds.setUrl(url);
		ds.setDriverClassName(driver);
		ds.setUsername(user);
		ds.setPassword(password);
		ds.setInitialSize(initSize);
		ds.setMaxWait(maxWait);
		return ds;
	}
}

7.创建dao层的接口,以及其实现类

package db.dao;

import db.bean.Account;

public interface IAccountDao {
	//通过id找account
	Account findById(long id);
	//修改余额
	void updateBalanceId(double balance,long id);
	//查看余额
	double lookBalanceId(long id);
}
package db.dao;

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

import db.bean.Account;

//让其表明是一个受spring容器管理起来的持久层对象@Repository
@Repository
public class AccountDaoImpl implements IAccountDao{

	@Autowired
	JdbcTemplate temp;
	
	
	@Override
	public Account findById(long id) {
		String sql = "select id,name,balance from account"
				+ " where id = ?";
		return temp.queryForObject(sql, (rs,rownum)->{
			Account ac = new Account();
			ac.setId(rs.getInt("id"));
			ac.setName(rs.getString("name"));
			ac.setBalance(rs.getDouble("balance"));
			return ac;
		},id);
	}

	@Override
	public void updateBalanceId(double balance, long id) {
		String sql = "update account set balance = ?"
				+ " where id = ?";
		temp.update(sql, balance,id);
		
	}

	@Override
	public double lookBalanceId(long id) {
		String sql = "select balance account"
				+ " where id = ?";
		return temp.queryForObject(sql, (rs,rownum)->{
			Account ac = new Account();
			
			ac.setBalance(rs.getDouble("balance"));
			return ac.getBalance();
		},id);
	}

}








8.创建service层的接口和实现类

package db.service;

public interface IAccountService {
	//from向to转账
	void transforTo(int fromAccount,int toAccount,double money);
	//查看两者的余额
	void see(int fromAccount,int toAccount);
}
package db.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import db.bean.Account;
import db.dao.IAccountDao;

@Service
public class AccountServiceImpl implements IAccountService{

	@Autowired
	private IAccountDao accountDao;
		
	//传入要转账人和收账人的id,以及转账金额
	@Override
	//添加事物管理如果转账过程中发生异常则回滚事物;
	@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
	public void transforTo(int fromAccount, int toAccount, double money) {
		Account from = accountDao.findById(fromAccount);
		Account to = accountDao.findById(toAccount);
		accountDao.updateBalanceId(10000, fromAccount);
		accountDao.updateBalanceId(10000, toAccount);
		
		if(from.getBalance()<money) {
			throw new RuntimeException("账户余额不足!");
		}
		
		accountDao.updateBalanceId(from.getBalance()-money, fromAccount);
		
		//假如在转账过程中有可能发生异常
		double r = Math.random();
		if(r<0.5) {
			throw new RuntimeException("转账过程中有发生异常");
		}
		
		accountDao.updateBalanceId(to.getBalance()+money, toAccount);
		
	}

	//查看两人的余额
	@Override
	public void see(int fromAccount, int toAccount) {
		Account from = accountDao.findById(fromAccount);
		Account to = accountDao.findById(toAccount);
		System.out.println("fromAccount的余额为:"+from.getBalance());
		System.out.println("toAccount的余额为:"+to.getBalance());
	}
	
}

9.为了在执行SQL语句时有日志输出写一个log4j.properties文件

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d [%-5p] %c - %m%n

#只显示debug级别的SQL语句相关日志
log4j.logger.org.springframework.jdbc.core.JdbcTemplate=DEBUG 

10.测试类

package spring_jd2007;


import java.util.Date;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import db.bean.Suser;
import db.config.DBAppConfig;
import db.dao.IUserDao;
import db.service.IAccountService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DBAppConfig.class)
public class DB_Test {
	@Autowired
	JdbcTemplate JdbcTemplate;
	
	@Autowired
	IAccountService accountService; 
	
	@Test
	public void TestTransaction() {
		accountService.transforTo(1, 2, 500);
		accountService.see(1, 2);
	}
	
}

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值