java 事务 数据库 事务_Java数据库编程——事务
我們可以將一組語(yǔ)句構(gòu)建成一個(gè)事務(wù)(transaction)。當(dāng)所有語(yǔ)句都順利執(zhí)行之后,事務(wù)可以提交(commit)。否則,如果其中某個(gè)語(yǔ)句遇到錯(cuò)誤,那么事務(wù)將被回滾,就好像沒(méi)有任何語(yǔ)句被執(zhí)行過(guò)一樣。
將多個(gè)語(yǔ)句組合成事務(wù)的主要原因是為了確保數(shù)據(jù)庫(kù)完整性(database integrity)。例如,假設(shè)我們需要將錢(qián)從一個(gè)銀行賬號(hào)轉(zhuǎn)移到另一個(gè)賬號(hào)。此時(shí),一個(gè)非常重要的問(wèn)題就是我們必須同時(shí)將錢(qián)從一個(gè)賬號(hào)取出并且存入另一個(gè)賬號(hào)。如果在將錢(qián)存入其他賬號(hào)之前系統(tǒng)發(fā)生崩潰,那么我們必須撤銷(xiāo)取款操作。
如果將更新語(yǔ)句組合成一個(gè)事務(wù),那么事務(wù)要么成功地執(zhí)行所有操作并提交,要么期間某個(gè)位置發(fā)生失敗。在這種情況下,可以執(zhí)行回滾(rollback)操作,則數(shù)據(jù)庫(kù)將自動(dòng)撤銷(xiāo)上次提交事務(wù)以來(lái)的所有更新操作產(chǎn)生的影響。
默認(rèn)情況下,數(shù)據(jù)庫(kù)連接處于自動(dòng)提交模式(autocommit mode)。每個(gè)SQL語(yǔ)句一旦被執(zhí)行便被提交給數(shù)據(jù)庫(kù)。一旦命令被提交,就無(wú)法對(duì)它進(jìn)行回滾操作。在使用事務(wù)時(shí),需要關(guān)閉這個(gè)默認(rèn)值:
conn.setAutoCommit(false);
現(xiàn)在可以使用通常的方法創(chuàng)建一個(gè)語(yǔ)句對(duì)象:
Statement stat = conn.createStatement();
然后任意多次調(diào)用executeUpdate方法:
stat.executeUpdate(command1);
stat.executeUpdate(command2);
stat.executeUpdate(command3);
...
如果執(zhí)行了所有命令之后沒(méi)有出錯(cuò),則調(diào)用commit方法:
conn.commit();
如果出現(xiàn)錯(cuò)誤,則調(diào)用:
conn.rollback();
此時(shí),程序?qū)⒆詣?dòng)撤銷(xiāo)自上次提交以來(lái)的所有語(yǔ)句。當(dāng)事務(wù)被SQLException異常中斷時(shí),典型的方法就是發(fā)起回滾操作。
1. 保存點(diǎn)
在使用某些驅(qū)動(dòng)程序時(shí),使用保存點(diǎn)(save point)可以更細(xì)粒度地控制回滾操作。創(chuàng)建一個(gè)保存點(diǎn)意味著稍候只需返回到這個(gè)點(diǎn),而非事務(wù)的開(kāi)頭。例如,
Statement stat = conn.createStatement(); //開(kāi)啟一個(gè)事務(wù);rollback()返回這里
stat.executeUpdate(command1);
Savepoint svpt= conn.setSavepoint(); //設(shè)置保存點(diǎn);rollback(svpt)返回到這里
stat.executeUpdate(command2);if(...) conn.rollback(svpt); //撤銷(xiāo)command2產(chǎn)生的影響
...
conn.commit();
當(dāng)不再需要保存點(diǎn)時(shí),必須釋放它:
conn.releaseSavepoint(svpt);
2. 批量更新
假設(shè)有一個(gè)程序需要執(zhí)行許多INSERT語(yǔ)句,以便將數(shù)據(jù)填入數(shù)據(jù)庫(kù)表中,此時(shí)可以使用批量更新的方法來(lái)提高程序性能。在使用批量更新(batch update)時(shí),一個(gè)語(yǔ)句序列作為一批操作將同時(shí)被收集和提交。
注意:使用DatabaseMetaData接口中的supportsBatchUpdates方法可以獲知數(shù)據(jù)庫(kù)是否支持這種特性。
處于同一批中的語(yǔ)句可以是INSERT、UPDATE和DELETE等操作,也可以是數(shù)據(jù)庫(kù)定義語(yǔ)句,如CREATE TABLE和DROP TABLE。但是,在批量處理中添加SELECT語(yǔ)句會(huì)拋出異常(從概念上講,批量處理中的SELECT語(yǔ)句沒(méi)有意義,因?yàn)樗鼤?huì)返回結(jié)果集,而不更新數(shù)據(jù)庫(kù))。
為了執(zhí)行批量處理,首先必須使用通常的辦法創(chuàng)建一個(gè)Statement對(duì)象:
Statement stat = conn.createStatement();
現(xiàn)在應(yīng)該調(diào)用addBatch方法,而非executeUpdate方法:
String command = "CREATE TABLE..."stat.addBatch(command);while(...){
command= "INSERT INTO ... VALUES("+...+")";
stat.addBatch(command);
}
最后,提交整個(gè)批量更新語(yǔ)句:
int[] counts = stat.executeBatch();
調(diào)用executeBatch方法將為所有已提交的語(yǔ)句返回一個(gè)記錄數(shù)的數(shù)組。
為了在批量模式下正確地處理錯(cuò)誤,必須將批量執(zhí)行的操作視為單個(gè)事務(wù)。如果批量更新在執(zhí)行過(guò)程中失敗,那么必須將它回滾到批量操作開(kāi)始之前的狀態(tài)。
首先,關(guān)閉自動(dòng)提交模式,然后收集批量操作,執(zhí)行并提交該操作,最后恢復(fù)最初的自動(dòng)提交模式:
boolean autoCommit =conn.getAutoCommit();
conn.setAutoCommit(false);
Statement stat=conn.getStatement();
...//keep calling stat.addBatch(...);
...
stat.executeBatch();
conn.commit();
conn.setAutoCommit(autoCommit);
總結(jié)
以上是生活随笔為你收集整理的java 事务 数据库 事务_Java数据库编程——事务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java barcode api_使用J
- 下一篇: java并发编程实践 读书笔记_Java