`
kyo100900
  • 浏览: 634765 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JDBC的事务初探

阅读更多

很久没有更新Blog,有点惭愧啊,呵呵,其实我一直在懵懵懂懂的学习事务处理。Spring把这一切封装的很好了,以至于我现在都无法正常写出一个像样的JDBC事务处理的程序,如果让我用JDBC写语句,还是有很多ASP的影子。无意中买了10月的《程序员》杂志,没想到里面讲了SQL Server的事务处理,我耐着性子看完了,于是我想把它转换成实际的Java代码。呵呵,言归正传,开始我们今天的旅行吧。

首先,我的平台是WindowsXP2+JDK1.5+myeclispe6.0+mysql5.037。这个环境配置可能与大家不一样,请注意一下。先建一个数据库,我用的是MySQL自带的test,在里面随便建立了一个表格,结构如下,大家可以随便建立,不必过于在意,因为是初探,所以开始不会有很复杂的内容,而且东西也是越简单越好,呵呵。

sql 代码
  1. DROP TABLE IF EXISTS `tbl_tran`;   
  2. CREATE TABLE `tbl_tran` (   
  3.   `id` int(10) unsigned NOT NULL auto_increment,   
  4.   `namevarchar(45) NOT NULL,   
  5.   `age` int(10) unsigned NOT NULL,   
  6.   `gender` char(1) NOT NULL,   
  7.   `memo` text,   
  8.   PRIMARY KEY  (`id`)   
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  

 

建立好了表,可以往里加入一个测试数据比如:

sql 代码
  1. INSERT INTO `tbl_tran` VALUES (1,'leo',0,'M','hello leo');  

一切都准备好了。开始写测试代码啦。

java 代码
  1. package com.leo.tran;   
  2.   
  3. import java.sql.Connection;   
  4. import java.sql.ResultSet;   
  5. import java.sql.SQLException;   
  6. import java.sql.Statement;   
  7.   
  8. import com.leo.jdbc.DBConnection;   
  9.   
  10. public class TranJDBC1 {   
  11.   
  12.     private static Connection conn;   
  13.     private static Connection conn_two;   
  14.   
  15.     // 要测试的某条记录   
  16.     private static String testName = "leo";   
  17.   
  18.     // 要测试的这条记录更新的一个字段   
  19.     private static int testAge = 23;   
  20.   
  21.     /**  
  22.      * 初始化两个连接,不使用单例  
  23.      */  
  24.     static {   
  25.         conn = DBConnection.getConnection();   
  26.         conn_two = DBConnection.getConnection();   
  27.         try {   
  28.             conn_two.setAutoCommit(false);   
  29.         } catch (SQLException e) {   
  30.             e.printStackTrace();   
  31.         }   
  32.     }   
  33.   
  34.     /**  
  35.      * 默认的事物处理级别为4 也就是:TRANSACTION_REPEATABLE_READ,支持可重复读  
  36.      *   
  37.      * @param conn  
  38.      * @return  
  39.      * @throws SQLException  
  40.      */  
  41.     public static int getDefaultTransactionIsolation(Connection conn)   
  42.             throws SQLException {   
  43.         return conn.getTransactionIsolation();   
  44.     }   
  45.   
  46.     /**  
  47.      * 更新测试记录  
  48.      */  
  49.     public static void updateTable(int age) {   
  50.         Statement stmt = null;   
  51.         try {   
  52.             stmt = conn_two.createStatement();   
  53.             stmt.executeUpdate("update tbl_tran set age = " + age   
  54.                     + " where name = '" + testName + "'");   
  55.             System.out.println("[数据库开始更新中..............]");   
  56.         } catch (SQLException e) {   
  57.             try {   
  58.                 conn_two.close();   
  59.             } catch (SQLException e1) {   
  60.                 e1.printStackTrace();   
  61.             }   
  62.         }   
  63.     }   
  64.   
  65.     /**  
  66.      * 查询测试记录信息  
  67.      */  
  68.     public static void selectTable() {   
  69.         Statement stmt = null;   
  70.         try {   
  71.             stmt = conn.createStatement();   
  72.             String sql = "select * from tbl_tran where name = '" + testName   
  73.                     + "'";   
  74.             ResultSet rs = stmt.executeQuery(sql);   
  75.             while (rs.next()) {   
  76.                 System.out   
  77.                         .println("===========================打印输出开始===============================");   
  78.                 System.out.println("[ID为: " + rs.getInt("id") + "]");   
  79.                 System.out.println("[Name为: " + rs.getString("name") + "]");   
  80.                 System.out.println("[age为: " + rs.getString("age") + "]");   
  81.                 System.out.println("[gender为: " + rs.getString("gender") + "]");   
  82.                 System.out.println("[memo为: " + rs.getString("memo") + "]");   
  83.                 System.out   
  84.                         .println("===========================打印输出结束===============================");   
  85.             }   
  86.         } catch (SQLException e) {   
  87.             try {   
  88.                 conn.close();   
  89.             } catch (SQLException e1) {   
  90.                 e1.printStackTrace();   
  91.             }   
  92.         }   
  93.     }   
  94.   
  95.     /**  
  96.      * 使用默认的自动提交的Connection测试  
  97.      * @throws SQLException  
  98.      */  
  99.     public static void testTransaction() throws SQLException {   
  100.         System.out.println("[查看需要测试的记录原始信息.........]");   
  101.         System.out.println("[未更新前的详细信息.........]");   
  102.         selectTable();   
  103.         System.out.println("[为了测试先把查询的conn的事务设置成提交读.........]");   
  104.         // Transaction isolation level NONE not supported by MySQL   
  105.         conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);   
  106.         // 设置conn_two为默认提交   
  107.         conn_two.setAutoCommit(true);   
  108.         updateTable(testAge);   
  109.         System.out.println("[更新后,但事务自动提交后记录的详细信息.........]");   
  110.         selectTable();   
  111.     }   
  112.   
  113.     /**  
  114.      * 关闭默认自动提交的Connection测试  
  115.      * @throws SQLException  
  116.      */  
  117.     public static void testTransaction2() throws SQLException {   
  118.         System.out.println("[查看需要更新的记录信息.........]");   
  119.         System.out.println("[未更新前的详细信息.........]");   
  120.         selectTable();   
  121.         System.out.println("[为了测试先把查询的conn的事务设置成提交读.........]");   
  122.         // 注意:Transaction isolation level NONE not supported by MySQL   
  123.         conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);   
  124.         updateTable(testAge);   
  125.         System.out.println("[更新后,但事务尚未提交时记录的详细信息.........]");   
  126.         selectTable();   
  127.         // 提交那个更新的Connection,然后再查询数据库   
  128.         conn_two.commit();   
  129.         System.out.println("[更新后,但事务提交后记录的详细信息.........]");   
  130.         selectTable();   
  131.   
  132.     }   
  133.   
  134.     public static void main(String[] args) throws SQLException {   
  135.         System.out.println("[先看看Connection默认事务处理级别为: "  
  136.                 + getDefaultTransactionIsolation(conn) + " ]");   
  137.         System.out.println();   
  138.         testTransaction();   
  139.   
  140.     }   
  141.   
  142. }  

条码很简单,就是两个方法:

1.testTransaction():大家在使用Connection的时候,常常容易使用默认的连接,而这个连接是默认提交的,不具备事务处理的能力,所以在测试中,即使你已经设置了另一个Conn的隔离级别,但仍然不起作用,呵呵,我在刚开始编程ASP的时候,要处理关联表,不知道事务的概念,常常是一个表有数据了,另一个表出问题了,或者是插入一半数据了,然后手工改,慢慢接触了Java,使用了Spring,才知道事务的概念很重要。

2.testTransaction2():是正确的使用方法。一个连接在访问一条记录,另一个连接却想更新这条记录,那么应该看到什么样的结果呢?这个时候,隔离级别就起作用了,这里用的是READ_COMMITED,即提交读,也就是说没有提交过的记录是看不到的。只有更新的那个Conn_two提交了,或者是回滚了,也就是说Conn_two的事务结束了,才可以看到最后的结果。打印的结果是:

 

java 代码
  1. [数据库已打开...........................]   
  2. [数据库已打开...........................]   
  3. [先看看Connection默认事务处理级别为: 4 ]   
  4.   
  5. [查看需要更新的记录信息.........]   
  6. [未更新前的详细信息.........]   
  7. ===========================打印输出开始===============================   
  8. [ID为: 1]   
  9. [Name为: leo]   
  10. [age为: 0]   
  11. [gender为: M]   
  12. [memo为: hello leo]   
  13. ===========================打印输出结束===============================   
  14. [为了测试先把查询的conn的事务设置成提交读.........]   
  15. [数据库开始更新中..............]   
  16. [更新后,但事务尚未提交时记录的详细信息.........]   
  17. ===========================打印输出开始===============================   
  18. [ID为: 1]   
  19. [Name为: leo]   
  20. [age为: 0]   
  21. [gender为: M]   
  22. [memo为: hello leo]   
  23. ===========================打印输出结束===============================   
  24. [更新后,但事务提交后记录的详细信息.........]   
  25. ===========================打印输出开始===============================   
  26. [ID为: 1]   
  27. [Name为: leo]   
  28. [age为: 23]   
  29. [gender为: M]   
  30. [memo为: hello leo]   
  31. ===========================打印输出结束===============================   

 

我的main()方法,测试的是testTransaction2(),而testTransaction()大家也可测试一下,了解有时候默认的配置并不是最合适的选择。这个主题还会继续补充的,今天先到这里吧。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics