使用事务实现银行转账操作

建表:

CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(30),
money FLOAT
);


INSERT INTO account(username,money) VALUES('wency',1000),
('tom',1000),
('mary',1000);


使用到的jar包有:

c3p0-0.9.1.2.jar

commons-dbutils-1.4.jar

mysql-connector-java-5.0.8-bin.jar


c3po工具类

package com.wency.utils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mysql.jdbc.ResultSet;

public class C3p0Utils {
	//创建ComboPooledDataSource对象
		private static DataSource dataSource=new ComboPooledDataSource();
		//获取连接的方法
		public static Connection getConnection(){
			try {
				return dataSource.getConnection();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				throw new RuntimeException("服务器出错");
			}
		}
		//获取数据源
		public  static DataSource getDataSource() {
			return dataSource;
		}
		//释放资源
		public static void release(Connection conn,PreparedStatement prsmt,ResultSet rs){
			if(conn!=null){
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				conn=null;
			}
			
			if(prsmt!=null){
				try {
					prsmt.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				prsmt=null;
			}
			
			if(rs!=null){
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				rs=null;
			}
			
		}
}

ThreadLocalUtil类

package com.wency.utils;

import java.sql.Connection;
import java.sql.SQLException;

public class ThreadLocalUtil {
	private static ThreadLocal<Connection> tl=new ThreadLocal<Connection>();
	
	/**
	 * 
	 * @return 从线程池中获取一个连接
	 */
	public static Connection getConnection(){
		Connection conn=tl.get();//从线程中获取连接
		//如果conn为空,则从线程池中取出 一个,如果不为空则直接返回原来那个
		//这样做的目的是为了确保事务操作时线程不被其他线程干扰
		if(conn==null){
			conn=C3p0Utils.getConnection();
			tl.set(conn);//将连接放到tl中去
		}
			return conn;
	}
	
	/**
	 * 开启事务
	 */
	public static void startTranscation(){
	    try {
			getConnection().setAutoCommit(false);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 提交事务
	 */
	public static void commit(){
		try {
			getConnection().commit();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 回滚事务
	 */
	public static void rollback(){
		try {
			getConnection().rollback();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * 释放资源
	 */
	public static void release(){
		try {
			getConnection().close();
			tl.remove();//关闭连接之后要将该线程移除
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
Account实体类

package com.wency.entity;

public class Account {
	private int id;
	private String username;
	float money;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public float getMoney() {
		return money;
	}
	public void setMoney(float money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "Account [id=" + id + ", username=" + username + ", money="
				+ money + "]";
	}
	
}

Dao接口

package com.wency.dao;


import com.wency.entity.Account;

public interface Dao {
	//修改账户操作
	 int updateAccount(String username,float money);
	//根据姓名查找账户
	 Account findAccountByName(String name);
}


Dao实现类

package com.wency.dao.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;



import com.wency.dao.Dao;
import com.wency.entity.Account;
import com.wency.utils.C3p0Utils;

public class DaoImpl implements Dao {
	
	private final String UPDATE="update account set money=? where username=?";
	private final String SELECT="select * from account where username=";
	
	 public DaoImpl() {
		// TODO Auto-generated constructor stub
	}
	@Override
	public  Account findAccountByName(String name) {
		// TODO Auto-generated method stub
		QueryRunner qr=new QueryRunner(C3p0Utils.getDataSource());
		List<Account> list=null;
		try {
			list = qr.query(SELECT+"'"+name+"'",new BeanListHandler<Account>(Account.class));
			return list.get(0);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
		
		}
		return null;
		
	}

	@Override
	public  int updateAccount(String username, float money) {
		// TODO Auto-generated method stub
		QueryRunner qr=new QueryRunner(C3p0Utils.getDataSource());
		try {
			int update = qr.update(UPDATE ,money,username);
			return update;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException("数据库操作异常");
		}
	}
}


Service接口
package com.wency.service;



public interface Service {
	void translate(float money,String fromName,String toName);
}
Service实现类
package com.wency.service.impl;

import com.wency.dao.Dao;
import com.wency.dao.impl.DaoImpl;
import com.wency.entity.Account;
import com.wency.service.Service;
import com.wency.utils.ThreadLocalUtil;

public class ServiceImpl implements Service {

	public void translate(float money, String username) {
		// TODO Auto-generated method stub
		
	}
	

	@Override
	public void translate(float money, String fromName, String toName) {
		// TODO Auto-generated method stub
		
		Dao dao=new DaoImpl();

		Account fromAccount=dao.findAccountByName(fromName);
		Account toAccount=dao.findAccountByName(toName);
		try {
			//开启事务
			ThreadLocalUtil.startTranscation();
			dao.updateAccount(fromName, fromAccount.getMoney()-money);
			dao.updateAccount(toName, toAccount.getMoney()+money);
			//提交事务
			ThreadLocalUtil.commit();
		} catch (Exception e) {
			// TODO: handle exception
			//如果出现异常,则回滚
			ThreadLocalUtil.rollback();
			throw new RuntimeException("操作失败");
		}finally{
			//最后将连接关闭
			ThreadLocalUtil.release();
		}
		
	
	}
	

}


测试类
import org.junit.Test;

import com.wency.dao.Dao;
import com.wency.dao.impl.DaoImpl;
import com.wency.entity.Account;
import com.wency.service.Service;
import com.wency.service.impl.ServiceImpl;


public class TestTranslate {
	@Test
	public void testTranslate(){
		Service service=new ServiceImpl();
		service.translate(500, "wency", "tom");
	}
	
	@Test
	public void testUpdate(){
		Dao dao=new DaoImpl();
		int updateAccount = dao.updateAccount("wency", 2000);
		System.out.println(updateAccount);
	}
	@Test
	public void testSelect(){
		Dao dao=new DaoImpl();
		Account account = dao.findAccountByName("wency");
		System.out.println(account);
		
	}
}



发布了38 篇原创文章 · 获赞 6 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/coderlady/article/details/56490304