日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java事务处理

發(fā)布時(shí)間:2025/3/11 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java事务处理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有個(gè)同學(xué)給我的文檔,直接發(fā)上來了,


在數(shù)據(jù)庫操作中,一項(xiàng)事務(wù)是指由一條或多條對(duì)數(shù)據(jù)庫更新的sql語句所組成的一個(gè)不可分割的工作單元。只有當(dāng)事務(wù)中的所有操作都正常完成了,整個(gè)事務(wù)才能被提交到數(shù)據(jù)庫,如果有一項(xiàng)操作沒有完成,就必須撤消整個(gè)事務(wù)。?



例如在銀行的轉(zhuǎn)帳事務(wù)中,假定張三從自己的帳號(hào)上把1000元轉(zhuǎn)到李四的帳號(hào)上,相關(guān)的sql語句如下:?

update account set monery=monery-1000 where name='zhangsan'?
update account set monery=monery+1000 where name='lisi'?


這個(gè)兩條語句必須作為一個(gè)完成的事務(wù)來處理。只有當(dāng)兩條都成功執(zhí)行了,才能提交這個(gè)事務(wù)。如果有一句失敗,整個(gè)事務(wù)必須撤消。?

在connection類中提供了3個(gè)控制事務(wù)的方法:?


(1) setAutoCommit(Boolean autoCommit):設(shè)置是否自動(dòng)提交事務(wù);?
(2) commit();提交事務(wù);?
(3) rollback();撤消事務(wù);?

在jdbc api中,默認(rèn)的情況為自動(dòng)提交事務(wù),也就是說,每一條對(duì)數(shù)據(jù)庫的更新的sql語句代表一項(xiàng)事務(wù),操作成功后,系統(tǒng)自動(dòng)調(diào)用commit()來提交,否則將調(diào)用rollback()來撤消事務(wù)。?

在jdbc api中,可以通過調(diào)用setAutoCommit(false) 來禁止自動(dòng)提交事務(wù)。然后就可以把多條更新數(shù)據(jù)庫的sql語句做為一個(gè)事務(wù),在所有操作完成之后,調(diào)用commit()來進(jìn)行整體提交。倘若其中一項(xiàng) sql操作失敗,就不會(huì)執(zhí)行commit()方法,而是產(chǎn)生相應(yīng)的sqlexception,此時(shí)就可以捕獲異常代碼塊中調(diào)用rollback()方法撤消事務(wù)。
? 示例:
? 有這樣一張名叫test_user的表:uid為1的money為0元,uid為2的money為300元,uid為3的money為800元。現(xiàn)在uid為3的人向uid為1的人轉(zhuǎn)賬,每次50元。當(dāng)uid為3的人的賬戶中的money少于或等于700的元的時(shí)候,則停止轉(zhuǎn)賬。也就是說,最后的uid為1的人賬戶為100元,uid為3的賬戶700元。
事務(wù)操作的基本流程是:當(dāng)達(dá)到某個(gè)條件時(shí)拋出一個(gè)異常,在這個(gè)異常處理中回滾操作。事務(wù)最大的一個(gè)特點(diǎn)是,要么全部執(zhí)行,要么不執(zhí)行。但是,對(duì)于使用JAVA來操作數(shù)據(jù)庫事務(wù)來說,并沒用我們想的那么簡單:下面這段代碼故意將某個(gè)字段寫錯(cuò),來檢驗(yàn)java是如何操作數(shù)據(jù)庫的事務(wù)的:


public class TransactionTest { public static void main(String[] args) throws Exception { Connection conn = ConnectionFactory.getInstance().getLocalConnection(); //換成自己的連接代碼int money=0; ResultSet rt=null; try { conn.setAutoCommit(false); //修改提交方式,關(guān)閉自動(dòng)提交模式Statement st =conn.createStatement(); String addMoneySql = "update test_user set money=money+50 where uid=1;"; int flag0= st.executeUpdate(addMoneySql); System.out.println(flag0); String reduceMoneySql = "update test_user set money=money-50 where uid=3"; int flag1 =st.executeUpdate(reduceMoneySql); System.out.println(flag1); String queryMoneySql="select money from test_user where uid=3"; rt=st.executeQuery(queryMoneySql); if(rt.next()){ money=rt.getInt("mone");//這里故意將字段打錯(cuò),檢驗(yàn)java如何執(zhí)行事務(wù)的,原字段為money System.out.println(money); } if(money<=700){ throw new RuntimeException("3號(hào)的錢已經(jīng)不夠了,不要匯款了");//拋出一個(gè)異常,在異常處理中回滾操作 } conn.commit(); } catch (Exception e) { e.printStackTrace();//打印出上面拋出來的異常,否則是不會(huì)顯示的。 if(conn!=null){ conn.rollback(); } } } }

執(zhí)行這段代碼。發(fā)現(xiàn)結(jié)果為:
?
1
1
java.sql.SQLException: Column 'mone' not found.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
at com.mysql.jdbc.ResultSet.findColumn(ResultSet.java:987)
at com.mysql.jdbc.ResultSet.getInt(ResultSet.java:2749)
at TransactionTest.main(TransactionTest.java:26)


在異常發(fā)生后,catch住異常,執(zhí)行了回滾操作,查看數(shù)據(jù)庫,數(shù)據(jù)庫數(shù)據(jù)并沒有發(fā)生變化。但是用update執(zhí)行的結(jié)果來看,update是執(zhí)行了的。這就說明java處理數(shù)據(jù)庫的事務(wù)的執(zhí)行策略:先挨句執(zhí)行(下一句的基本數(shù)據(jù)是上一句執(zhí)行完畢的數(shù)據(jù),而不是數(shù)據(jù)庫真實(shí)的數(shù)據(jù)),當(dāng)出現(xiàn)回滾時(shí)候,直接通知數(shù)據(jù)庫回滾。數(shù)據(jù)庫回滾以后并不會(huì)通知java,所以就會(huì)出現(xiàn)打印執(zhí)行結(jié)果與數(shù)據(jù)庫數(shù)據(jù)不一致的情況。


那么,這一段代碼中money(假設(shè)字段已經(jīng)修改正常)的值會(huì)是多少呢?
首先 uid 1 加50,uid 3 減50,成功執(zhí)行,打印出750
然后 uid 1加 50 uid 3減 50,此時(shí) uid 3中的money為 700(發(fā)現(xiàn)異常,回滾)結(jié)果數(shù)據(jù)庫中的uid還是750,而打印出來的值卻是 700.
再執(zhí)行。發(fā)現(xiàn)依舊會(huì)拋出3號(hào)錢已經(jīng)不夠的異常。
當(dāng)然,我們會(huì)思考,我們重新執(zhí)行這段代碼的話,java是不會(huì)從數(shù)據(jù)庫中間取得數(shù)據(jù),而是直接使用臟數(shù)據(jù)。而且關(guān)閉連接等資源,關(guān)閉eclispe都不起作用,只有重新啟動(dòng)數(shù)據(jù)庫,才能使得java從數(shù)據(jù)庫讀數(shù)據(jù)。
當(dāng)然了,將事務(wù)按照合理的方式編排就不會(huì)出現(xiàn)這種錯(cuò)誤。比如,將select語句放在uid 3之前,就不會(huì)出錯(cuò)了。 。(其實(shí)對(duì)于事務(wù)操作,依舊讀的是臟數(shù)據(jù),只不過這個(gè)臟數(shù)據(jù)與實(shí)際數(shù)據(jù)一致罷了。)

總結(jié)

以上是生活随笔為你收集整理的java事务处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。