事务-模拟银行用户转账
SQL数据:
我这里准备了两个用户的数据,模拟一下在事务下的银行转账
DROP TABLE IF EXISTS `shiwu`; CREATE TABLE `shiwu` ( `id` int(4) NOT NULL AUTO_INCREMENT, `name` varchar(10) DEFAULT NULL, `money` double(10,2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; INSERT INTO `shiwu` VALUES ('1', 'zhangsan', '1500.00'); INSERT INTO `shiwu` VALUES ('2', 'lisi', '2000.00');
+----+----------+-------+
| id | name | money |
+----+----------+-------+
| 1 | zhangsan | 1500 |
| 2 | lisi | 2000 |
+----+----------+-------+
银行转账代码:
import java.sql.*; public class Demo { public static void main(String[] args) { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; try { //1、注册驱动 Class.forName("com.mysql.jdbc.Driver"); ///2、获取连接(数据库对象) conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/donglijiedian", "root", "zhixi158"); //3、关闭事务的自动提交,就是开启事务 conn.setAutoCommit(false); //4、获取预编译的数据库操作对象(业务代码) String sql1 = "update shiwu set `money` = money+500 where `name` = 'zhangsan'"; ps = conn.prepareStatement(sql1); //4.1、执行更新 int count = ps.executeUpdate(); /** * 如果让中间这个地方出现异常,那么余额就会是错误的了,第二条SQL语句并没有执行 * 会出现: * java.lang.NullPointerException(空指针异常) * JDBC 中的事务是自动提交的:只要执行一条语句就提交一次 * 解决办法:使用手动事务 */ //String s = null; //s.toString(); String sql2 = "update shiwu set `money` = money-500 where `name` = 'lisi'"; ps = conn.prepareStatement(sql2); count += ps.executeUpdate(); System.out.println(count == 2 ? "转账成功" : "转账失败"); //4.1.1、序能走到这里,说明上面没有出现异常,将事务进行手动提交 conn.commit(); //4.1.2、使用完毕后开启事务的自动提交 conn.setAutoCommit(true); } catch (SQLException | ClassNotFoundException e) { //4.2、更新数据失败就回滚 try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); } finally { //6、释放资源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
测试: