13-jdbc分页+事务
一、 jdbc分頁
1. 什么是分頁
在數(shù)據(jù)量較大的情況下,我們會(huì)數(shù)據(jù)分作多頁顯示,讓用戶瀏覽起來更加的方便,可以根據(jù)頁碼去翻閱每一頁的數(shù)據(jù)
?
2. 如何實(shí)現(xiàn)分頁的分析
說到分頁,一般都會(huì)立刻想到先將數(shù)據(jù)存入集合,再將數(shù)據(jù)分作多頁顯示,這樣的做法固然可以,可是一旦數(shù)據(jù)量較大的話就會(huì)造成內(nèi)存的溢出,再者說,大部分用戶的瀏覽習(xí)慣都是只看前三頁,如果數(shù)據(jù)總共有100頁,那就完全沒必要將數(shù)據(jù)全部從數(shù)據(jù)庫中查出來了,所以一個(gè)普遍的實(shí)現(xiàn)方式都是根據(jù)用戶需要瀏覽的頁碼,從數(shù)據(jù)庫中查詢一頁的數(shù)據(jù)供用戶瀏覽
?
分頁的目的就是為了更加合理地做頁面顯示,所以首先要解決的就是頁面需要顯示哪些數(shù)據(jù)
通常來講,頁面上會(huì)顯示當(dāng)前頁的信息、當(dāng)前第幾頁、總共多少頁、頁碼、上一頁、下一頁等信息
我們可以使用一個(gè) Page 對(duì)象來封裝頁面需要實(shí)現(xiàn)的數(shù)據(jù)
在service中計(jì)算出 Page 對(duì)象所需的數(shù)據(jù)
Service中需要的一些來自于數(shù)據(jù)庫的數(shù)據(jù)就找 Dao 索取
?
3. 分頁的具體實(shí)現(xiàn)
1)根據(jù)需求設(shè)計(jì)Page對(duì)象
2)dao的實(shí)現(xiàn)
?????? 兩個(gè)方法
?????? int getTotalRecord(); ??? // 獲得總記錄數(shù)
?????? List getPageData(int start, int len);? // 獲得分頁數(shù)據(jù)
3)service 實(shí)現(xiàn)
?????? Page getPage(int pageNum);? // 計(jì)算分頁數(shù)據(jù)
4)Servlet
?????? 獲得頁面提交的 pageNum
?????? 找service計(jì)算出分頁數(shù)據(jù)? Page
?????? 轉(zhuǎn)發(fā)給jsp 做分頁顯示
?
二、 jdbc 事務(wù)
1. 什么是事務(wù)
所謂事務(wù),就是針對(duì)數(shù)據(jù)庫的一組操作(多條sql)
特點(diǎn):位于同一個(gè)事務(wù)的操作具備同步的特點(diǎn),也就是要么都成功,要么都失敗
?
2. 事務(wù)的作用
在實(shí)際中,我們的很多操作都是需要由多條sql來共同完成的,例如,A賬戶給B賬戶轉(zhuǎn)賬就會(huì)對(duì)應(yīng)兩條sql
update account set money=money-100 where name=‘a’;
update account set money=money+100 where name=‘b’;
提交事務(wù)?? 提交事務(wù)中的所有操作
假設(shè)第一條sql成功了,而第二條sql失敗了,這樣就會(huì)導(dǎo)致a賬戶損失了100元,而b賬戶并未得到100元
?
如果將兩條sql放在一個(gè)sql中,當(dāng)?shù)诙l語句失敗時(shí),第一條sql語句也同樣不會(huì)生效,
這樣a賬戶就不會(huì)有任何的損失
?
?
3. 事務(wù)的實(shí)現(xiàn)原理
默認(rèn)情況下,我們向數(shù)據(jù)庫發(fā)送的sql語句是會(huì)被自動(dòng)提交的,開啟事務(wù)就是相當(dāng)于關(guān)閉自動(dòng)提交功能,改為手動(dòng)提交,我們只需要將提交事務(wù)的操作放在最后一個(gè)操作,這樣一來,如果在提交事務(wù)之前出現(xiàn)異常,由于沒有執(zhí)行提交操作,事務(wù)中未提交的操作就會(huì)被回滾掉
?
4. 例子
account.sql
create table account(
?????? id int primary key auto_increment,
?????? name varchar(40),
?????? money float
)character set utf8 collate utf8_general_ci;
?
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
?
aaa 給 bbb 轉(zhuǎn)賬 100元
update account set money=money-100 where name='aaa';
// 異常退出
update account set money=money+100 where name='bbb';
?
// 查詢結(jié)果
select * from accont;
?
如果開啟事務(wù)就可以避免剛才的錯(cuò)誤發(fā)生
// 開啟事務(wù)
start transaction;
?
// 如果操作執(zhí)行完畢,我們需要將事務(wù)提交
commit;
?
// 還可以手動(dòng)回顧事務(wù)中所有未提交的事務(wù)
rollback;
?
命令行做實(shí)驗(yàn)得出結(jié)論:
如果開了一個(gè)事務(wù),又敲了一次 start transaction 再次開啟事務(wù),前一個(gè)事務(wù)會(huì)自動(dòng)提交
?
5、在程序中使用 jdbc 開啟事務(wù)
在使用 jdbc 操作數(shù)據(jù)庫時(shí),需要使用 Connection 對(duì)象對(duì)事務(wù)進(jìn)行管理
// 開啟事務(wù)
Connection.setAutoCommit(false);?????? //設(shè)置自動(dòng)提交為false
// 回滾事務(wù)
Connection.rollback();??
//提交事務(wù)
Connection.commit();???
?
在 jdbc 程序中我們還可以設(shè)置回滾點(diǎn),讓事務(wù)回顧到指定的回滾點(diǎn),而不是自動(dòng)回滾所有未提交的操作
需要將程序中的異常捕獲,在catch語句塊中回滾事務(wù),在finally中提交事務(wù)
注意,將 Commit 操作放在 finally 中是為了保證提交未回滾的事務(wù)操作
?
6. 事務(wù)的特性
事務(wù)有四大特性,一般來講,判斷一個(gè)數(shù)據(jù)庫是否支持事務(wù),就看數(shù)據(jù)庫是否支持這四個(gè)特性
l? 原子性(Atomicity)
原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。?
?
l? 一致性(Consistency)
事務(wù)必須使數(shù)據(jù)庫從一個(gè)一致性狀態(tài)變換到另外一個(gè)一致性狀態(tài)。
?
l? 隔離性(Isolation)
事務(wù)的隔離性是多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫時(shí),數(shù)據(jù)庫為每一個(gè)用戶開啟的事務(wù),不能被其他事務(wù)的操作數(shù)據(jù)所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。
?
l? 持久性(Durability)
持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對(duì)其有任何影響。
?
7. 事務(wù)的隔離級(jí)別
1)多線程開啟事務(wù)
?????? 由于數(shù)據(jù)庫是多線程并發(fā)訪問的,所以很容易出現(xiàn)多個(gè)線程同時(shí)開啟事務(wù)的情況
?????? 多線程開事務(wù)容易引起贓讀、不可重復(fù)讀、幻讀的情況發(fā)生
?
?????? 贓讀:dirty read
?????? 是指一個(gè)事務(wù)讀取了另一個(gè)事務(wù)未提交的數(shù)據(jù),這是相當(dāng)危險(xiǎn)的。
?????? 設(shè)想一下,A要給B轉(zhuǎn)賬100元購買商品,如果A開啟了一個(gè)事務(wù)做了轉(zhuǎn)賬的工作
?????? update account set money=money+100 while name=‘b’;??????
?????? update account set money=money -100 while name=‘a(chǎn)’;
?????? A先不提交事務(wù),通知B來查詢
?????? 這時(shí)B來查詢賬戶,由于會(huì)讀到A開啟的事務(wù)中未提交的數(shù)據(jù),就會(huì)發(fā)現(xiàn)A確實(shí)給自己轉(zhuǎn)了100元,
?????? 自然就會(huì)給A發(fā)貨,A等B發(fā)貨后就將事務(wù)回滾,不提交,此時(shí),B就會(huì)受到損失
??????
?????? 不可重復(fù)讀:non-repeatable read
?????? 是指事務(wù)中兩次查詢的結(jié)果不一致,原因是在查詢的過程中其他事務(wù)做了更新的操作 update
?????? 例如,銀行做報(bào)表,第一次查詢A賬戶有100元,第二次查詢A賬戶有200元,原因是期間A存了100元
?????? 這樣就會(huì)導(dǎo)致銀行多次統(tǒng)計(jì)的報(bào)表不一致
?
和臟讀的區(qū)別是:
臟讀是讀取前一事務(wù)未提交的臟數(shù)據(jù),不可重復(fù)讀是在事務(wù)內(nèi)重復(fù)讀取了別的線程已提交的數(shù)據(jù)。
?
有的時(shí)候大家會(huì)認(rèn)為這樣的結(jié)果是正確的,沒問題
我們可以考慮這樣一種情況,比如銀行程序需要將查詢結(jié)果分別輸出到電腦屏幕和寫到文件中,結(jié)果在一個(gè)事務(wù)中針對(duì)輸出的目的地,進(jìn)行的兩次查詢不一致,導(dǎo)致文件和屏幕中的結(jié)果不一致,銀行工作人員就不知道以哪個(gè)為準(zhǔn)了。
?
幻讀:phantom read??? 又名虛讀
是指在一個(gè)事務(wù)內(nèi)兩次查詢中數(shù)據(jù)筆數(shù)不一致
幻讀和不可重復(fù)讀有些類似,是指兩次查詢過程中,其他事務(wù)做了插入記錄的操作,導(dǎo)致記錄數(shù)有所增加
insert
?
例如銀行做報(bào)表統(tǒng)計(jì)account表中所有用戶的總額時(shí),此時(shí)總共
?????? 五個(gè)賬戶,總金額為500元,這時(shí)有一個(gè)新的賬戶產(chǎn)生了,并且
?????? 存了100元,這時(shí)銀行再統(tǒng)計(jì)會(huì)發(fā)現(xiàn)帳戶總金額為600元了,造
?????? 成虛讀同樣會(huì)使銀行遇到同樣的困惑
?
?????? 實(shí)驗(yàn)發(fā)現(xiàn)不會(huì)出現(xiàn)虛讀
?????? 來自網(wǎng)絡(luò)的解釋:
?????? 幻讀只是在理論上會(huì)發(fā)生的一種情況,而現(xiàn)實(shí)操作中并不是一定會(huì)發(fā)生
?
2)設(shè)置事務(wù)的隔離級(jí)別
?????? 為了避免多線程開事務(wù)引發(fā)的問題,我們需要將事務(wù)進(jìn)行隔離
?????? 事務(wù)有四種隔離級(jí)別,不同的隔離級(jí)別可以防止不同的錯(cuò)誤發(fā)生
?????? serializable:可串行化,能避免臟讀、不可重復(fù)讀、幻讀情況的發(fā)生
repeatable read:可重讀,能避免臟讀、不可重復(fù)讀情況的發(fā)生(實(shí)際上mysql在實(shí)現(xiàn)的時(shí)候避免了虛讀)
read committed:讀取提交的內(nèi)容,可避免臟讀情況發(fā)生
read uncommitted:讀取未提交的內(nèi)容,最低級(jí)別,避免不了任何情況
?
操作:
設(shè)置事務(wù)隔離級(jí)別
set?? transaction isolation level
查詢當(dāng)前事務(wù)隔離級(jí)別
select @@tx_isolation??
?
總結(jié)
以上是生活随笔為你收集整理的13-jdbc分页+事务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 德军装甲军团的秘密武器
- 下一篇: 库尔斯克坦克大会战:二个硬汉的生死决斗