JAVA事务及隔离级别

Java事务


1)       说到事务,不得不提的就是ACID特性,再次回顾:

  Ø  原子性(atomicity):组成事务处理的语句形成了一个逻辑单元,不能只执行其中的一部分。

  Ø  一致性(consistency):在事务处理执行前后,数据库是一致的(数据库数据完整性约束)。

  Ø  隔离性(isolcation):一个事务处理对另一个事务处理的影响。

  Ø  持续性(durability):事务处理的效果能够被永久保存下来 。

2)       然后就是事务在Java中的最基本操作:

  Ø  connection.setAutoCommit(false);//打开事务。

  Ø  connection.commit();//提交事务。

  Ø  connection.rollback();//回滚事务。

  这里需要提的就是,当只想撤销事务中的部分操作时可使用SavePoint

  Ø  SavePoint sp = connection.setSavepoint();

  Ø  connection.rollerbak(sp);connection.commit();

3)       下面用一个实例代码来展示一下:

[java] view plain copy
  1. package cn.itcast.jdbc;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.ResultSet;  
  5. import java.sql.SQLException;  
  6. import java.sql.Savepoint;  
  7. import java.sql.Statement;  
  8. /** 
  9.  * 事务测试 
  10.  */  
  11. public class SavePointTest {  
  12.   
  13.     public static void main(String[] args) throws SQLException {  
  14.         testTransaction();  
  15.     }  
  16.   
  17.     static void testTransaction() throws SQLException {  
  18.         Connection conn = null;  
  19.         Statement st = null;  
  20.         ResultSet rs = null;  
  21.         Savepoint sp = null;  
  22.         try {  
  23.             //获取Connection(JdbcUtils为自定义的包装类,这里不做解释)  
  24.             conn = JdbcUtils.getConnection();  
  25.             //开启事务  
  26.             conn.setAutoCommit(false);            
  27.             st = conn.createStatement();  
  28.             //id为1的人的Money减10  
  29.             String sql = "update user set money=money-10 where id=1";  
  30.             st.executeUpdate(sql);  
  31.             //********************回滚界限***************************  
  32.             //设置回滚点(savepoint)  
  33.             sp = conn.setSavepoint();  
  34.             //********************回滚界限***************************  
  35.             //id为2的人的Money减10  
  36.             sql = "update user set money=money-10 where id=3";  
  37.             st.executeUpdate(sql);        
  38.             sql = "select money from user where id=2";  
  39.             rs = st.executeQuery(sql);  
  40.             float money = 0.0f;  
  41.             if (rs.next()) {  
  42.                 money = rs.getFloat("money");  
  43.             }  
  44.             if (money > 300){  
  45.                 throw new RuntimeException("已经超过最大值!");  
  46.             }  
  47.             //id为2的人的Money加10  
  48.             sql = "update user set money=money+10 where id=2";  
  49.             st.executeUpdate(sql);  
  50.             //提交事务  
  51.             conn.commit();  
  52.         } catch (RuntimeException e) {  
  53.             if (conn != null && sp != null) {  
  54.                 //回滚事务,注意里面的参数sp即为我们上面设置的savePoint,如果回滚的话只能回滚到savePoint以下的部分  
  55.                 //上面的部分不会得到回滚  
  56.                 conn.rollback(sp);  
  57.                 conn.commit();  
  58.             }  
  59.             throw e;  
  60.         } catch (SQLException e) {  
  61.             if (conn != null)  
  62.                 conn.rollback();  
  63.             throw e;  
  64.         } finally {  
  65.             //释放资源(JdbcUtils为自定义类)  
  66.             JdbcUtils.free(rs, st, conn);  
  67.         }  
  68.     }  
  69. }  

  上面所有的操作(CRUD)都是在同一个数据源上的操作,无法处理跨多数据源(分布式)操作。跨多个数据源的事务就要使用JTA容器实现事务。根本思想就是“分成两阶段提交”,具体内容这里不做介绍。

[java] view plain copy
  1. javax.transaction.UserTransaction tx = (UserTransaction)ctx.lookup(“jndiName");  
  2.     tx.begin();  
  3.     //connection1 connection2 (可能来自不同的数据库)…   
  4.     tx.commit();//tx.rollback();  

隔离级别


1)      为了应对多线程并发读取数据时出现的问题,事务有了“隔离级别”特性,多线程并发读取数据一般会引发如下三个问题

  Ø  脏读(dirtyreads)

  Ø  不可重复读(non-repeatablereads)

  Ø  幻读(phantomread)

下面进行简要介绍:

  Ø  脏读:一个事务读取了另一个未提交的并行事务写的数据。

  Ø  不可重复读:一个事务重新读取前面读取过的数据, 发现该数据已经被另一个已提交的事务修改过。

  Ø  幻读:一个事务重新执行一个查询,返回一套符合查询条件的行, 发现这些行因为其他最近提交的事务而发生了改变。

2)       为了处理上面的读数据问题,java事务提供了4种隔离级别,如下:

  Ø  读未提交(Read uncommitted)

  Ø  读已提交(Readcommitted)

  Ø  可重复读(Repeatableread)

  Ø  可串行化(Serializable)

3)       4种隔离级别与上面3个问题的对应关系如下:


  JAVA事务及隔离级别_第1张图片

  注意上面的“可能”二字。


4)       隔离级别的设定:

  connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

  在代码中的应用:

  JAVA事务及隔离级别_第2张图片


总结


  除了隔离级别,上面所有的东西在.net中相信大家都很熟悉。当然在八期的.net教务系统也用到了事务隔离级别这一点,当时自己还是初步接触,现在可以详细的学习,可以看到学习就是一个不断反复的过程。

你可能感兴趣的:(JDBC)