Java事務
1) 說到事務,不得不提的就是ACID特性,再次回顧: java
Ø 原子性(atomicity):組成事務處理的語句造成了一個邏輯單元,不能只執行其中的一部分。 sql
Ø 一致性(consistency):在事務處理執行先後,數據庫是一致的(數據庫數據完整性約束)。 數據庫
Ø 隔離性(isolcation):一個事務處理對另外一個事務處理的影響。 多線程
Ø 持續性(durability):事務處理的效果可以被永久保存下來 。 併發
2) 而後就是事務在Java中的最基本操做: 分佈式
Ø connection.setAutoCommit(false);//打開事務。 學習
Ø connection.commit();//提交事務。 測試
Ø connection.rollback();//回滾事務。 atom
這裏須要提的就是,當只想撤銷事務中的部分操做時可以使用SavePoint: spa
Ø SavePoint sp = connection.setSavepoint();
Ø connection.rollerbak(sp);connection.commit();
3) 下面用一個實例代碼來展現一下:
- package cn.itcast.jdbc;
-
- import java.sql.Connection;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Savepoint;
- import java.sql.Statement;
- /**
- * 事務測試
- */
- public class SavePointTest {
-
- public static void main(String[] args) throws SQLException {
- testTransaction();
- }
-
- static void testTransaction() throws SQLException {
- Connection conn = null;
- Statement st = null;
- ResultSet rs = null;
- Savepoint sp = null;
- try {
- //獲取Connection(JdbcUtils爲自定義的包裝類,這裏不作解釋)
- conn = JdbcUtils.getConnection();
- //開啓事務
- conn.setAutoCommit(false);
- st = conn.createStatement();
- //id爲1的人的Money減10
- String sql = "update user set money=money-10 where id=1";
- st.executeUpdate(sql);
- //********************回滾界限***************************
- //設置回滾點(savepoint)
- sp = conn.setSavepoint();
- //********************回滾界限***************************
- //id爲2的人的Money減10
- sql = "update user set money=money-10 where id=3";
- st.executeUpdate(sql);
- sql = "select money from user where id=2";
- rs = st.executeQuery(sql);
- float money = 0.0f;
- if (rs.next()) {
- money = rs.getFloat("money");
- }
- if (money > 300){
- throw new RuntimeException("已經超過最大值!");
- }
- //id爲2的人的Money加10
- sql = "update user set money=money+10 where id=2";
- st.executeUpdate(sql);
- //提交事務
- conn.commit();
- } catch (RuntimeException e) {
- if (conn != null && sp != null) {
- //回滾事務,注意裏面的參數sp即爲咱們上面設置的savePoint,若是回滾的話只能回滾到savePoint如下的部分
- //上面的部分不會獲得回滾
- conn.rollback(sp);
- conn.commit();
- }
- throw e;
- } catch (SQLException e) {
- if (conn != null)
- conn.rollback();
- throw e;
- } finally {
- //釋放資源(JdbcUtils爲自定義類)
- JdbcUtils.free(rs, st, conn);
- }
- }
- }
上面全部的操做(CRUD)都是在同一個數據源上的操做,沒法處理跨多數據源(分佈式)操做。跨多個數據源的事務就要使用JTA容器實現事務。根本思想就是「分紅兩階段提交」,具體內容這裏不作介紹。
- javax.transaction.UserTransaction tx = (UserTransaction)ctx.lookup(「jndiName");
- tx.begin();
- //connection1 connection2 (可能來自不一樣的數據庫)…
- tx.commit();//tx.rollback();
隔離級別
1) 爲了應對多線程併發讀取數據時出現的問題,事務有了「隔離級別」特性,多線程併發讀取數據通常會引起以下三個問題:
Ø 髒讀(dirtyreads)
Ø 不可重複讀(non-repeatablereads)
Ø 幻讀(phantomread)
下面進行簡要介紹:
Ø 髒讀:一個事務讀取了另外一個未提交的並行事務寫的數據。
Ø 不可重複讀:一個事務從新讀取前面讀取過的數據, 發現該數據已經被另外一個已提交的事務修改過。
Ø 幻讀:一個事務從新執行一個查詢,返回一套符合查詢條件的行, 發現這些行由於其餘最近提交的事務而發生了改變。
2) 爲了處理上面的讀數據問題,java事務提供了4種隔離級別,以下:
Ø 讀未提交(Read uncommitted)
Ø 讀已提交(Readcommitted)
Ø 可重複讀(Repeatableread)
Ø 可串行化(Serializable)
3) 4種隔離級別與上面3個問題的對應關係以下:
注意上面的「可能」二字。
4) 隔離級別的設定:
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
在代碼中的應用:
總結
除了隔離級別,上面全部的東西在.net中相信你們都很熟悉。固然在八期的.net教務系統也用到了事務隔離級別這一點,當時本身仍是初步接觸,如今能夠詳細的學習,能夠看到學習就是一個不斷反覆的過程。
http://blog.csdn.net/wang379275614/article/details/24818397