经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MySQL » 查看文章
【JDBC】笔记(4)--- JDBC 事务自动提交机制;账户转账演示事务代码(bug版+修正版)
来源:cnblogs  作者:猿头猿脑的王狗蛋  时间:2022/1/2 16:27:30  对本文有异议

楔子:

   JDBC 的事务默认是自动提交的:

   只要执行一条 DML语句,则自动提交一次。但是在实际的业务中,通常是多条 DML语句 联合完成的,那么就必须保证这些 DML语句 在同一个事务中同时成功或失败!!!

   否则这会是一个非常严重的bug!!!


/*
1、功能:实现转账功能(bug版)
2、需求:演示一下 JDBC事务 默认自动提交存在的隐患
3、t_act:(原表)
        +-------+---------+
        | actno | balance |
        +-------+---------+
        |  5566 | 1000.00 |
        |  1314 |    0.00 |
        +-------+---------+

*/

 

  1. import java.sql.*;
  2. /**
  3. *sql脚本:
  4. * drop t_act if exists;
  5. * create table t_act(
  6. * actno int,
  7. * balance double(7,2)
  8. * );
  9. * insert into t_act(actno,balance) values(5566,1000);
  10. * insert into t_act(actno,balance) values(1314,0);
  11. */
  12. public class JDBCTransactionTest01 {
  13. public static void main(String[] args) {
  14. Connection connection = null;
  15. PreparedStatement ps = null;
  16. int count = 0;
  17. try {
  18. Class.forName("com.mysql.cj.jdbc.Driver");
  19. connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode"
  20. , "root", "888");
  21. String sql = "update t_act set balance = ? where actno = ?";
  22. ps = connection.prepareStatement(sql);
  23. ps.setDouble(1, 0);
  24. ps.setDouble(2, 5566);
  25. count = ps.executeUpdate();
  26. String s = null;
  27. s.toString();
  28. String sql0 = "update t_act set balance = ? where actno = ?";
  29. ps = connection.prepareStatement(sql0);
  30. ps.setDouble(1, 1000);
  31. ps.setDouble(2, 1314);
  32. count += ps.executeUpdate();
  33. System.out.println("更新数据:" + count + "条");
  34. } catch (Exception e) {
  35. e.printStackTrace();
  36. } finally {
  37. if (ps != null) {
  38. try {
  39. ps.close();
  40. } catch (SQLException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. if (connection != null) {
  45. try {
  46. connection.close();
  47. } catch (SQLException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. System.out.println(count == 2?"转账成功":"转账失败");
  52. }
  53. }
  54. }

 

IDEA控制台输出结果:

  1. java.lang.NullPointerException
  2. at com.bjpowernode.jdbc.JDBCTransactionTest01.main(JDBCTransactionTest01.java:48)
  3. 转账失败
  4. Process finished with exit code 0

 

现在瞅一眼 t_act:

  +-------+---------+
  | actno | balance |
  +-------+---------+
  |  5566 |    0.00 |
  |  1314 |    0.00 |
  +-------+---------+

哎呀我去,这bug太严重了,钱都飞了!!


/*
1、功能:实现转账功能(修正版)                  

2、需求;使每次同一转账事务中,多条 DML语句 同时成功/同时失败

3、t_act:(原表)
        +-------+---------+
        | actno | balance |
        +-------+---------+
        |  5566 | 1000.00 |
        |  1314 |    0.00 |
        +-------+---------+

*/

 

  1. import java.sql.*;
  2. public class JDBCTransactionTest02 {
  3. public static void main(String[] args) {
  4. Connection connection = null;
  5. PreparedStatement ps = null;
  6. int count = 0;
  7. try {
  8. Class.forName("com.mysql.cj.jdbc.Driver");
  9. connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode"
  10. , "root", "888");
  11. //将自动提交机制修改为手动提交
  12. connection.setAutoCommit(false);
  13. String sql = "update t_act set balance = ? where actno = ?";
  14. ps = connection.prepareStatement(sql);
  15. ps.setDouble(1, 0);
  16. ps.setDouble(2, 5566);
  17. count = ps.executeUpdate();
  18. String s = null;
  19. s.toString();
  20. String sql0 = "update t_act set balance = ? where actno = ?";
  21. ps = connection.prepareStatement(sql0);
  22. ps.setDouble(1, 1000);
  23. ps.setDouble(2, 1314);
  24. count += ps.executeUpdate();
  25. System.out.println("更新数据:" + count + "条");
  26. //程序执行到这说明没有异常,事务结束,手动提交数据
  27. connection.commit();
  28. } catch (Exception e) {
  29. //如果出现异常,回滚事务
  30. if (connection != null) {
  31. try {
  32. connection.rollback();
  33. } catch (SQLException ex) {
  34. ex.printStackTrace();
  35. }
  36. }
  37. e.printStackTrace();
  38. } finally {
  39. if (ps != null) {
  40. try {
  41. ps.close();
  42. } catch (SQLException e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. if (connection != null) {
  47. try {
  48. connection.close();
  49. } catch (SQLException e) {
  50. e.printStackTrace();
  51. }
  52. }
  53. System.out.println(count == 2?"转账成功":"转账失败");
  54. }
  55. }
  56. }

 

IDEA控制台输出结果:

  1. java.lang.NullPointerException
  2. at com.bjpowernode.jdbc.JDBCTransactionTest02.main(JDBCTransactionTest02.java:31)
  3. 转账失败
  4. Process finished with exit code 0

 

现在瞅一眼 t_act:

  +-------+---------+
  | actno | balance |
  +-------+---------+
  |  5566 | 1000.00 |
  |  1314 |    0.00 |
  +-------+---------+

虽然因为某些原因导致转账失败,但是数据库中储存的数据一切正常,而且控制台也给出了提示(转账失败),所以总结:此转账程序非常成功!


 

原文链接:http://www.cnblogs.com/Burning-youth/p/15757466.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号