Mysql数据库事务实验以及总结

   为了做这个实验,设计个场景,要把用户2 上账户的22块钱打一块钱到账户1的账上去。要么全成功,全失败,也就是账要做平。

    代码如下:

其中最关键的是:

updateMoneyByUserId(1, getMoneyByUserId(1) + 1,false); //这条语句是否回滚

updateMoneyByUserId(2, getMoneyByUserId(2) - 1,true); //设置抛出异常,

当用户2在打钱时抛出异常,没成功时,用户1的更新要回滚回来。在mysql connection中默认是自动提交的,需要设置为手动提交,然后才可用rollback方法进行回滚。

package com.test.transaction;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


/**
 CREATE TABLE `usermoney` (
  `user_id` int(11) NOT NULL DEFAULT '0',
  `moneyNum` int(11) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='user for money';


INSERT INTO `usermoney` VALUES (1,11),(2,22),(3,33),(4,44),(5,55);
 * */
public class TranTest {

static Connection connection;
static {
try {
// 加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 连续数据库
connection = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/banker", "root", "123456");
if (!connection.isClosed()) {
System.out.println("created connetion...:" + connection);
}
} catch (Exception e) {
e.printStackTrace();
}
}


public static void main(String[] args) throws InterruptedException {


try {
//手工设置数据库为一个初始状态,并提交
connection.setAutoCommit(false);//默认为自动提交
updateMoneyByUserId(1, 11,false);
updateMoneyByUserId(2, 22,false);
connection.commit();

//查询是否是设置正确1 --11 ; 2 --22
System.out.println("userID=1 & moneyNum=" + getMoneyByUserId(1));
System.out.println("userID=2 & moneyNum=" + getMoneyByUserId(2));

//如果更新是抛异常,需要注意回滚
connection.setAutoCommit(false);
updateMoneyByUserId(1, getMoneyByUserId(1) + 1,false); //这条语句是否回滚

updateMoneyByUserId(2, getMoneyByUserId(2) - 1,true); //设置抛出异常,

//如果抛异常,下面语句不再执行
System.out.println("userID=1 & moneyNum=" + getMoneyByUserId(1));
System.out.println("userID=2 & moneyNum=" + getMoneyByUserId(2));

//如果不抛异常,不提交会怎样?(结束时还是会做一次提交)
connection.commit(); 

} catch (SQLException e) {
try {
e.printStackTrace();
//开始回滚
connection.rollback();
//数据库是否还是正确的呢?1==11 ; 2==22
System.out.println("check if userId=1 and moneyNum==11-->userID=1 & moneyNum=" + getMoneyByUserId(1));
System.out.println("check if userId=2 and moneyNum==22-->userID=2 & moneyNum=" + getMoneyByUserId(2));
} catch (SQLException e1) {
e.printStackTrace();
}
}
Thread.sleep(10000L);


}
/**
* 通过UserId获取Money number
* */
public static int getMoneyByUserId(int userId) throws SQLException {
// 执行SQL语句
Statement statement = connection.createStatement();
// 要执行的SQL语句
String sql = "select user_id,moneyNum from usermoney where user_id="
+ userId;
statement.execute(sql);
ResultSet rs = statement.executeQuery(sql);
rs.next();
return new Integer(rs.getString("moneyNum"));
}
/**
* 更新用户金额
* */
public static void updateMoneyByUserId(int userId, int moneyNum,boolean showThrow)
throws SQLException {
// 执行SQL语句
if (showThrow) {
throw new SQLException("不让你存");

}
Statement statement = connection.createStatement();
// 要执行的SQL语句
String sql = "update usermoney set moneyNum=" + moneyNum
+ " where user_id=" + userId;
System.out.println(sql);
statement.executeUpdate(sql);
}
}
通过以上代码实验,我们还可以得出一个经验。

在一个方法中同时操作本地数据库和调用远程接口时,要先把本地数据库事务操作完成后,再调用远程接口。

因为如果先调用接口,再操作本地数据库事务是抛出异常,再回滚时,本地数据库就和远程接口数据不一致了。

如果先操作本地数据库,抛出异常还可以自己决定一次是否要调用远程接口。

现在比较大的项目,常用spring来做事务管理,接下来做更多的这方面研究。

转载于:https://my.oschina.net/u/177808/blog/184337

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值