mySql事务模型银行转账,自己写的,写的不好仅作参考。

要点:事务必须同一connection;使用线程名把connection存入HashMap或者ThreadLocal中,提交事务后注意关闭,否则后续操作其他方法如果是同一connection,会出现代码正常执行完毕,但是数据库数据值未变化,原因就是未关闭事务所以代码执行完毕未提交。

开启事务:

connection.setAutoCommit(false);

提交完毕后应该执行:

connection.setAutoCommit(true);

转账方法:changeMoney

package com.dream.mysqltest;

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

import com.dream.mysqltest.DBUtils.DBUtils;


public class Test02 {
	private static boolean b = false;//用来辨别是否为转账方法
	public static void main(String[] args) throws Throwable {
		
		Test02 test02 = new Test02();
		test02.changeMoney("小明", "小红", 200);
//		test02.addMoney("小明", 200);
//		test02.addMoney("小明", 200);
//		test02.addMoney("小红", 200);
//		test02.reduceMoney("小红", 200);
//		test02.reduceMoney("小明", 200);
//		
		
	}
	
	
	//转帐的方法
	//resourceName转出人名字
	//targetName转入人名字
	//changeMoney交易金额
	public void changeMoney(String resourceName,String targetName , int changeMoney) {
		 b = true;//表示正在进行转账
		synchronized (Test02.class) {
			
			try {
				Test02 test02 = new Test02();
				DBUtils.startTransaction();
				
				test02.reduceMoney(resourceName, changeMoney);//先减少
				test02.addMoney(targetName, changeMoney);//再增加
				System.out.println(resourceName + "向" + targetName + "转账" + changeMoney +"成功");
				DBUtils.myCommit();
				
			} catch (SQLException e) {
				DBUtils.myRollback();
				System.out.println("转账失败");
			}
		}
			b = false;
		
	}
	
	//存钱的方法
	public void addMoney(String username, int money) throws SQLException{

		synchronized (Test02.class) {
		PreparedStatement prepareStatement = null;
		PreparedStatement querysStatement = null;
		// 获取连接对象
		Connection connection = DBUtils.getMyConnection();
		// 获取statement对象
		// 使用prepareStatement防止SQL注入
		// 发送sql语句
		String add = "update A set money=money+? where username = ?";
		String query = "select * from A where username = ?";
		prepareStatement = connection.prepareStatement(add);
		querysStatement = connection.prepareStatement(query);
		// 设置?的值1是money的值,2是改变的名字;
		prepareStatement.setInt(1, money);
		prepareStatement.setString(2, username);
		querysStatement.setString(1, username);
		//存入
		prepareStatement.executeUpdate();
		//查询余额
		ResultSet resultSet = querysStatement.executeQuery();
		if (!b) {
		System.out.println(username + "存入" + money + "元成功");
		}
		 while (resultSet.next()) {
				int int1 = resultSet.getInt("money");
					System.out.println( username +"剩余余额为"+int1+"元");
			}
		 if (!b) {
			 DBUtils.myClose(null, querysStatement, resultSet);
			 DBUtils.myClose(connection, prepareStatement, null);
		}else if (b) {
			DBUtils.myClose(null, querysStatement, resultSet);
			DBUtils.myClose(connection, prepareStatement, null);
			
		}
		}
	}
	//取钱的方法
	public void reduceMoney(String username, int money) throws SQLException{
		synchronized (Test02.class) {
		PreparedStatement prepareStatement = null;
		PreparedStatement querysStatement = null;
		// 获取连接对象
		Connection connection = DBUtils.getMyConnection();
		// 获取statement对象
		// 使用prepareStatement防止SQL注入
		// 发送sql语句
		String sql = "update A set money=money-? where username = ?";
		String query = "select * from A where username = ?";
		prepareStatement = connection.prepareStatement(sql);
		querysStatement = connection.prepareStatement(query);
		// 设置?的值1是money的值,2是改变的名字;
		prepareStatement.setInt(1, money);
		prepareStatement.setString(2, username);
		querysStatement.setString(1, username);
		prepareStatement.executeUpdate();
		ResultSet resultSet = querysStatement.executeQuery();
		if (!b) {
		System.out.println(username + "取出" + money + "元成功");
		}
		 while (resultSet.next()) {
			int int1 = resultSet.getInt("money");
			System.out.println( username +"剩余余额为"+int1+"元");
		}
		 if (!b) {
			 DBUtils.myClose(null, querysStatement, resultSet);
			 DBUtils.myClose(connection, prepareStatement, null);
		}
		}
	}
}

DBUtils工具类:

package com.dream.mysqltest.DBUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Properties;



public class DBUtils {
	private static String driverName;
	private static String url;
	private static String username;
	private static String password;
	private static HashMap<String, Connection> hashMap = new HashMap<String, Connection>();
	
	static {
		try {
//			//创建配置文件对象
			Properties properties = new Properties();
			//把配置文件加载到此对象中
			properties.load(new FileInputStream(new File("D:\\WakeSpace\\mysql02\\config\\DBConfig.properties")));
			//通过配置文件中的key获取value
			driverName = properties.getProperty("driverName");
			url = properties.getProperty("url");
			username = properties.getProperty("username");
			password = properties.getProperty("password");
			//加载jdbc驱动;
			Class.forName(driverName);
		} catch (ClassNotFoundException e) {
			System.out.println(e);
		} catch (IOException e) {
			System.out.println(e);
		}
		
		
	}
//	开启事务:start transaction
	public static void startTransaction() {
		
		Connection connection = getMyConnection();
		try {
			connection.setAutoCommit(false);
			hashMap.put(Thread.currentThread().getName(), connection);
		} catch (SQLException e) {
			System.out.println("开启事务失败");
		}
	} 
//	提交事务:commit;
	public static void myCommit() {
		Connection connection = hashMap.get(Thread.currentThread().getName());
//		判断connection是否为空,为空就不进行提交
		if (connection != null) {
			try {
				connection.commit();
				connection.setAutoCommit(true);
				hashMap.put(Thread.currentThread().getName(), null);
			} catch (SQLException e) {
			System.out.println("提交事务失败,请确认是否开启设置了事务自动提交");
			}
		}else {
			System.out.println("您还未开启事务,请开启。。。");
		}
	}
	
//	回滚事务:rollback
	public static void myRollback() {
		Connection connection = hashMap.get(Thread.currentThread().getName());
		//判断是否为空值
		if (connection != null) {
			try {
				connection.rollback();
				System.out.println("SQL异常,请检查SQl语句");
				connection.setAutoCommit(true);
				hashMap.put(Thread.currentThread().getName(), null);
			} catch (SQLException e) {
				System.out.println("回滚过程中发生异常,请检查是否开启了事务");
			}
		}else {
			System.out.println("您还未开启事务,请开启。。。");
		}
		
	}
	
	
	
	public static Connection getMyConnection() {
	//获取连接
		Connection conn = hashMap.get(Thread.currentThread().getName());
		if (conn == null) {
			try {
				conn = DriverManager.getConnection(url, username, password);
				hashMap.put(Thread.currentThread().getName(), conn);
			} catch (SQLException e) {
				System.out.println("获取连接失败");
			}
		}
	//返回connection对象
		return conn;
	}
	
	//关闭资源的方法
	public static void myClose(Connection connection,PreparedStatement prepareStatement,ResultSet resultSet) {
		
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (SQLException e) {
			}
			
		if (prepareStatement != null) {
			try {
				prepareStatement.close();

			} catch (SQLException e) {
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
			}
		}
			
		}
	}
	
}

配置文件:
driverName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/sqltest
username=root
password=root

你可能感兴趣的:(mySql事务模型银行转账,自己写的,写的不好仅作参考。)