激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術(shù)及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java事務管理學習之JDBC詳解

Java事務管理學習之JDBC詳解

2020-09-02 09:46oscar999 Java教程

這篇文章主要介紹了Java事務管理學習之JDBC的相關(guān)資料,文中介紹的非常詳細,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。

什么是Java事務

通常的觀念認為,事務僅與數(shù)據(jù)庫相關(guān)。

事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)的縮寫。事務的原子性表示事務執(zhí)行過程中的任何失敗都將導致事務所做的任何修改失效。一致性表示當事務執(zhí)行失敗時,所有被該事務影響的數(shù)據(jù)都應該恢復到事務執(zhí)行前的狀態(tài)。隔離性表示在事務執(zhí)行過程中對數(shù)據(jù)的修改,在事務提交之前對其他事務不可見。持久性表示已提交的數(shù)據(jù)在事務執(zhí)行失敗時,數(shù)據(jù)的狀態(tài)都應該正確。

通俗的理解,事務是一組原子操作單元,從數(shù)據(jù)庫角度說,就是一組SQL指令,要么全部執(zhí)行成功,若因為某個原因其中一條指令執(zhí)行有錯誤,則撤銷先前執(zhí)行過的所有指令。更簡答的說就是:要么全部執(zhí)行成功,要么撤銷不執(zhí)行。

既然事務的概念從數(shù)據(jù)庫而來,那Java事務是什么?之間有什么聯(lián)系?

實際上,一個Java應用系統(tǒng),如果要操作數(shù)據(jù)庫,則通過JDBC來實現(xiàn)的。增加、修改、刪除都是通過相應方法間接來實現(xiàn)的,事務的控制也相應轉(zhuǎn)移到Java程序代碼中。因此,數(shù)據(jù)庫操作的事務習慣上就稱為Java事務。

事務的特性:

1) 原子性(atomicity):事務是數(shù)據(jù)庫的邏輯工作單位,而且是必須是原子工作單位,對于其數(shù)據(jù)修改,要么全部執(zhí)行,要么全部不執(zhí)行。

2) 一致性(consistency):事務在完成時,必須是所有的數(shù)據(jù)都保持一致狀態(tài)。在相關(guān)數(shù)據(jù)庫中,所有規(guī)則都必須應用于事務的修改,以保持所有數(shù)據(jù)的完整性。

3) 隔離性(isolation):一個事務的執(zhí)行不能被其他事務所影響。

4) 持久性(durability):一個事務一旦提交,事物的操作便永久性的保存在DB中。即使此時再執(zhí)行回滾操作也不能撤消所做的更改。

事務(Transaction):是并發(fā)控制的單元,是用戶定義的一個操作序列。這些操作要么都做,要么都不做,是一個不可分割的工作單位。通過事務,sql server 能將邏輯相關(guān)的一組操作綁定在一起,以便服務器 保持數(shù)據(jù)的完整性。事務通常是以begin transaction開始,以commit或rollback結(jié)束。Commint表示提交,即提交事務的所有操作。具體地說就是將事務中所有對數(shù)據(jù)的更新寫回到磁盤上的物理數(shù)據(jù)庫中去,事務正常結(jié)束。Rollback表示回滾,即在事務運行的過程中發(fā)生了某種故障,事務不能繼續(xù)進行,系統(tǒng)將事務中對數(shù)據(jù)庫的所有已完成的操作全部撤消,滾回到事務開始的狀態(tài)。

自動提交事務:每條單獨的語句都是一個事務。每個語句后都隱含一個commit。 (默認)

顯式事務:以begin transaction顯示開始,以commit或rollback結(jié)束。

隱式事務:當連接以隱式事務模式進行操作時,sql server數(shù)據(jù)庫引擎實例將在提交或回滾當前事務后自動啟動新事務。無須描述事物的開始,只需提交或回滾每個事務。但每個事務仍以commit或rollback顯式結(jié)束。連接將隱性事務模式設置為打開之后,當數(shù)據(jù)庫引擎實例首次執(zhí)行下列任何語句時,都會自動啟動一個隱式事務:alter table,insert,create,open ,delete,revoke ,drop,select, fetch ,truncate table,grant,update在發(fā)出commit或rollback語句之前,該事務將一直保持有效。在第一個事務被提交或回滾之后,下次當連接執(zhí)行以上任何語句時,數(shù)據(jù)庫引擎實例都將自動啟動一個新事務。該實例將不斷地生成隱性事務鏈,直到隱性事務模式關(guān)閉為止。

JDBC事務管理

在使用JDBC的時候, 如何進行事務的管理。直接看一下代碼

示例代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
 * @Title: JDBCTrans.java
 * @Package com.oscar999.trans
 * @Description:
 * @author XM
 * @date Feb 14, 2017 4:38:27 PM
 * @version V1.0
 */
package com.oscar999.trans;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
 
/**
 * @author
 *
 */
public class JDBCTrans {
 
 public JDBCTrans() {
 
 }
 
 /**
 *
 * @param sHostName
 * @param sPortNumber
 * @param sSid
 * @param userName
 * @param password
 * @return
 * @throws SQLException
 */
 public Connection getConnection(String sHostName, String sPortNumber, String sSid, String userName, String password) throws SQLException {
 Connection conn = null;
 String url = getOraclURL(sHostName, sPortNumber, sSid);
 conn = DriverManager.getConnection(url,userName,password);
 return conn;
 }
 
 /**
 *
 * @param conn
 * @param sql
 * @throws SQLException
 */
 public void add(Connection conn, String sql) throws SQLException {
 Statement stmt = null;
 try {
  stmt = conn.createStatement();
  stmt.execute(sql);
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } finally {
  if (stmt != null)
  stmt.close();
 }
 }
 
 /**
 * @param args
 */
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 String sHostName = "";
 String sPortNumber = "";
 String sSid = "";
 String userName = "";
 String password = "";
 
 sHostName = "";
 sPortNumber = "";
 sSid = "";
 userName = "";
 password = "";
 
 try {
  Class.forName("oracle.jdbc.driver.OracleDriver");
 } catch (ClassNotFoundException e1) {
  // TODO Auto-generated catch block
  e1.printStackTrace();
 }
  
 JDBCTrans jdbcTrans = new JDBCTrans();
 Connection conn = null;
 try
  conn = jdbcTrans.getConnection(sHostName, sPortNumber, sSid, userName, password);
  conn.setAutoCommit(false);// can't insert, update
  
  //1. add SQL
  String addSQL = "insert into TEST_TABLE values('name1','value1')";
  jdbcTrans.add(conn,addSQL);
  
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } finally {
  /*if (conn != null)
  {
  try {
   conn.close();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  }*/
 }
 
 }
 
 private String getOraclURL(String sHostName, String sPortNumber, String sSid) {
 String url = "jdbc:oracle:thin:@" + sHostName + ":" + sPortNumber + ":" + sSid;
 return url;
 }
 
}

針對以上代碼, 說明如下:

以上代碼有幾點說明的部分:

1. conn.setAutoCommit(false) 執(zhí)行之后不提交事務。

對于Select沒有影響, 但對于Insert和Update的話, 沒有提交數(shù)據(jù)就不會被修改

2.  conn.close(); 關(guān)閉Connection的代碼有被Mark掉, 是想呈現(xiàn)conn.setAutoCommit(false)的效果。

原因是在 Connection Close的時候會執(zhí)行一次Commit.

而如果Connection是在應用服務器中使用連接池的話, Connection就不會被Close, 也就不會執(zhí)行Commit.

3. setAutoCommit(false) 用法大多數(shù)是在要執(zhí)行多條語句才提交。

所以針對以上第三點, 更接近實際的狀況的代碼如示例代碼2

示例代碼2

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
 * @Title: JDBCTrans.java
 * @Package com.oscar999.trans
 * @Description:
 * @author XM
 * @date Feb 14, 2017 4:38:27 PM
 * @version V1.0
 */
package com.oscar999.trans;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
 
/**
 * @author
 *
 */
public class JDBCTrans {
 
 public JDBCTrans() {
 
 }
 
 /**
 *
 * @param sHostName
 * @param sPortNumber
 * @param sSid
 * @param userName
 * @param password
 * @return
 * @throws SQLException
 */
 public Connection getConnection(String sHostName, String sPortNumber, String sSid, String userName, String password) throws SQLException {
 Connection conn = null;
 String url = getOraclURL(sHostName, sPortNumber, sSid);
 conn = DriverManager.getConnection(url, userName, password);
 return conn;
 }
 
 /**
 *
 * @param conn
 * @param sql
 * @throws SQLException
 */
 public void add(Connection conn, String sql) throws SQLException {
 Statement stmt = null;
 try {
  stmt = conn.createStatement();
  stmt.execute(sql);
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 } finally {
  if (stmt != null)
  stmt.close();
 }
 }
 
 /**
 * @param args
 */
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 String sHostName = "";
 String sPortNumber = "";
 String sSid = "";
 String userName = "";
 String password = "";
 
 sHostName = "";
 sPortNumber = "";
 sSid = "";
 userName = "";
 password = "";
 
 try {
  Class.forName("oracle.jdbc.driver.OracleDriver");
 } catch (ClassNotFoundException e1) {
  // TODO Auto-generated catch block
  e1.printStackTrace();
 }
 
 JDBCTrans jdbcTrans = new JDBCTrans();
 Connection conn = null;
 try {
  conn = jdbcTrans.getConnection(sHostName, sPortNumber, sSid, userName, password);
  conn.setAutoCommit(false);// can't insert, update
 
  // 1. add SQL 1
  String addSQL = "insert into TEST_TABLE values('name1','value1')";
  jdbcTrans.add(conn, addSQL);
 
  //2. add SQL 2
  addSQL = "insert into TEST_TABLE values('name2','value2')";
  jdbcTrans.add(conn, addSQL);
  
  conn.commit();
 } catch (SQLException e) {
  // TODO Auto-generated catch block
  if(conn!=null){
   try {
   conn.rollback();
   } catch (SQLException e1) {
   e1.printStackTrace();
   }
  
  e.printStackTrace();
 } finally {
  if (conn != null) {
  try {
   conn.close();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  }
 }
 
 }
 
 private String getOraclURL(String sHostName, String sPortNumber, String sSid) {
 String url = "jdbc:oracle:thin:@" + sHostName + ":" + sPortNumber + ":" + sSid;
 return url;
 }
 
}

這里需要說明的是: conn.rollback();

只要執(zhí)行有異常,就要rollback , 這一步必不可少

如果沒有在執(zhí)行出現(xiàn)異常的時候進行回滾。如果在執(zhí)行第一條語句之后出現(xiàn)異常,con既沒有提交也沒有回滾,表就會被鎖住(如果oracle數(shù)據(jù)庫就是行鎖),而這個鎖卻沒有機會釋放。

可能在執(zhí)行con.close()的時候會釋放鎖,但還是如果應用服務器使用了數(shù)據(jù)庫連接池,連接不會被斷開。

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家學習或者使用java能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 麻豆蜜桃在线观看 | 一本色道久久99精品综合蜜臀 | 亚洲一区二区中文字幕在线观看 | 一级黄色片武则天 | 久久精品伊人网 | 中国3xxxx | julieann艳星激情办公室 | 狠狠干天天操 | 成人黄视频在线观看 | 一级免费特黄视频 | av在线直播观看 | 素人视频在线观看免费 | 久久亚洲视频网 | 国产精品久久久久久久久久久久久久久久 | 嗯啊羞羞视频 | 91看片网页| 男女无遮挡羞羞视频 | 精精国产xxxx视频在线野外 | 中国美女一级黄色片 | 成人在线观看一区二区三区 | 中国黄色一级生活片 | 亚洲影视在线观看 | 日本欧美一区二区三区视频麻豆 | 欧美精品欧美极品欧美激情 | 久久精品成人影院 | 性爱在线免费视频 | 日韩黄色片免费看 | 国产一级毛片a | 一级大片一级一大片 | videos真实高潮xxxx | 亚洲码无人客一区二区三区 | 91豆奶| 成人乱码一区二区三区不卡视频 | 国产91久久久久久 | 黄色免费在线网址 | 黄视频网站免费在线观看 | 成人午夜看片 | 欧洲精品久久久久69精品 | 国产毛片毛片毛片 | 国产精品亚洲一区二区三区在线观看 | 成人毛片免费在线 |