亞馬遜網(wǎng)站特色如何在百度上添加自己的店鋪
目錄
75、闡述 JDBC 操作數(shù)據(jù)庫(kù)的步驟。
76、Statement 和 PreparedStatement 有什么區(qū)別?哪個(gè)性 能更好?
77、使用 JDBC 操作數(shù)據(jù)庫(kù)時(shí),如何提升讀取數(shù)據(jù)的性能?如何提升更新數(shù)據(jù)的性能?
78、在進(jìn)行數(shù)據(jù)庫(kù)編程時(shí),連接池有什么作用?
79、什么是 DAO 模式?
80、事務(wù)的 ACID 是指什么?
81、JDBC 中如何進(jìn)行事務(wù)處理?
75、闡述 JDBC 操作數(shù)據(jù)庫(kù)的步驟。
下面的代碼以連接本機(jī)的 Oracle 數(shù)據(jù)庫(kù)為例,演示 JDBC 操作數(shù)據(jù)庫(kù)的步驟。
加載驅(qū)動(dòng):
Class.forName("oracle.jdbc.driver.OracleDriver");
創(chuàng)建連接:
Connection con =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl",
"scott", "tiger");
創(chuàng)建語句:
PreparedStatement ps = con.prepareStatement("select * from emp where sal between ? and ?");
ps.setInt(1, 1000);
ps.setInt(2, 3000);
執(zhí)行語句:
ResultSet rs = ps.executeQuery();
處理結(jié)果:
while(rs.next()) {
System.out.println(rs.getInt("empno") + " - " + rs.getString("ename"));
}
關(guān)閉資源:
finally {if(con != null) {try {con.close();}}catch (SQLException e) {e.printStackTrace();
}
}
提示:關(guān)閉外部資源的順序應(yīng)該和打開的順序相反,也就是說先關(guān)閉 ResultSet、再關(guān)閉 Statement、在關(guān)閉 Connection。上面的代碼只關(guān)閉了 Connection(連接),雖然通常情況下在關(guān)閉連接時(shí),連接上創(chuàng)建的語句和打開的游標(biāo)也會(huì)關(guān)閉,但不能保證總是如此,因此應(yīng)該按照剛才說的順序分別關(guān)閉。此外,第一步加載驅(qū)動(dòng)在 JDBC 4.0 中是可以省略的(自動(dòng)從類路徑中加載驅(qū)動(dòng)),但是我們建議保留。
76、Statement 和 PreparedStatement 有什么區(qū)別?哪個(gè)性 能更好?
????????與 Statement 相比,①PreparedStatement 接口代表預(yù)編譯的語句,它主要的優(yōu)勢(shì)在于可以減少 SQL 的編譯錯(cuò)誤并增加 SQL 的安全性(減少 SQL 注射攻擊的可能性);②PreparedStatement 中的 SQL 語句是可以帶參數(shù)的,避免了用字符串連接拼接 SQL 語句的麻煩和不安全;③當(dāng)批量處理 SQL 或頻繁執(zhí)行相同的查詢時(shí),PreparedStatement 有明顯的性能上的優(yōu)勢(shì),由于數(shù)據(jù)庫(kù)可以將編譯優(yōu)化后的SQL 語句緩存起來,下次執(zhí)行相同結(jié)構(gòu)的語句時(shí)就會(huì)很快(不用再次編譯和生成執(zhí)行計(jì)劃)。
補(bǔ)充:為了提供對(duì)存儲(chǔ)過程的調(diào)用,JDBC API 中還提供了 CallableStatement 接口。存儲(chǔ)過程(Stored Procedure)是數(shù)據(jù)庫(kù)中一組為了完成特定功能的 SQL 語句的集合,經(jīng)編譯后存儲(chǔ)在數(shù)據(jù)庫(kù)中,用戶通過指定存儲(chǔ)過程的名字并給出參數(shù)(如果該存儲(chǔ)過程帶有參數(shù))來執(zhí)行它。雖然調(diào)用存儲(chǔ)過程會(huì)在網(wǎng)絡(luò)開銷、安全性、性能上獲得很多好處,但是存在如果底層數(shù)據(jù)庫(kù)發(fā)生遷移時(shí)就會(huì)有很多麻煩,因?yàn)槊糠N數(shù)據(jù)庫(kù)的存儲(chǔ)過程在書寫上存在不少的差別。
77、使用 JDBC 操作數(shù)據(jù)庫(kù)時(shí),如何提升讀取數(shù)據(jù)的性能?如何提升更新數(shù)據(jù)的性能?
????????要提升讀取數(shù)據(jù)的性能,可以指定通過結(jié)果集(ResultSet)對(duì)象的 setFetchSize()方法指定每次抓取的記錄數(shù)(典型的空間換時(shí)間策略);要提升更新數(shù)據(jù)的性能可以使用 PreparedStatement 語句構(gòu)建批處理,將若干 SQL 語句置于一個(gè)批處理中執(zhí)行。
78、在進(jìn)行數(shù)據(jù)庫(kù)編程時(shí),連接池有什么作用?
????????由于創(chuàng)建連接和釋放連接都有很大的開銷(尤其是數(shù)據(jù)庫(kù)服務(wù)器不在本地時(shí),每次建立連接都需要進(jìn)行 TCP 的三次握手,釋放連接需要進(jìn)行 TCP 四次握手,造成的開銷是不可忽視的),為了提升系統(tǒng)訪問數(shù)據(jù)庫(kù)的性能,可以事先創(chuàng)建若干連接置于連接池中,需要時(shí)直接從連接池獲取,使用結(jié)束時(shí)歸還連接池而不必關(guān)閉連接,從而避免頻繁創(chuàng)建和釋放連接所造成的開銷,這是典型的用空間換取時(shí)間的策略(浪費(fèi)了空間存儲(chǔ)連接,但節(jié)省了創(chuàng)建和釋放連接的時(shí)間)。池化技術(shù)在Java 開發(fā)中是很常見的,在使用線程時(shí)創(chuàng)建線程池的道理與此相同?;?Java 的開源數(shù)據(jù)庫(kù)連接池主要有:C3P0、Proxool、DBCP、BoneCP、Druid 等。
補(bǔ)充:在計(jì)算機(jī)系統(tǒng)中時(shí)間和空間是不可調(diào)和的矛盾,理解這一點(diǎn)對(duì)設(shè)計(jì)滿足性能要求的算法是至關(guān)重要的。大型網(wǎng)站性能優(yōu)化的一個(gè)關(guān)鍵就是使用緩存,而緩存跟上面講的連接池道理非常類似,也是使用空間換時(shí)間的策略。可以將熱點(diǎn)數(shù)據(jù)置于緩存中,當(dāng)用戶查詢這些數(shù)據(jù)時(shí)可以直接從緩存中得到,這無論如何也快過去數(shù)據(jù)庫(kù)中查詢。當(dāng)然,緩存的置換策略等也會(huì)對(duì)系統(tǒng)性能產(chǎn)生重要影響,對(duì)于這個(gè)問題的討論已經(jīng)超出了這里要闡述的范圍。
79、什么是 DAO 模式?
????????DAO(Data Access Object)顧名思義是一個(gè)為數(shù)據(jù)庫(kù)或其他持久化機(jī)制提供了抽象接口的對(duì)象,在不暴露底層持久化方案實(shí)現(xiàn)細(xì)節(jié)的前提下提供了各種數(shù)據(jù)訪問操作。在實(shí)際的開發(fā)中,應(yīng)該將所有對(duì)數(shù)據(jù)源的訪問操作進(jìn)行抽象化后封裝在一個(gè)公共 API 中。用程序設(shè)計(jì)語言來說,就是建立一個(gè)接口,接口中定義了此應(yīng)用程序中將會(huì)用到的所有事務(wù)方法。在這個(gè)應(yīng)用程序中,當(dāng)需要和數(shù)據(jù)源進(jìn)行交互的時(shí)候則使用這個(gè)接口,并且編寫一個(gè)單獨(dú)的類來實(shí)現(xiàn)這個(gè)接口,在邏輯上該類對(duì)應(yīng)一個(gè)特定的數(shù)據(jù)存儲(chǔ)。DAO 模式實(shí)際上包含了兩個(gè)模式,一是 DataAccessor(數(shù)據(jù)訪問器),二是 Data Object(數(shù)據(jù)對(duì)象),前者要解決如何訪問數(shù)據(jù)的問題,而后者要解決的是如何用對(duì)象封裝數(shù)據(jù)。
80、事務(wù)的 ACID 是指什么?
原子性(Atomic):事務(wù)中各項(xiàng)操作,要么全做要么全不做,任何一項(xiàng)操作的失敗都會(huì)導(dǎo)致整個(gè)事務(wù)的失敗;
一致性(Consistent):事務(wù)結(jié)束后系統(tǒng)狀態(tài)是一致的;
隔離性(Isolated):并發(fā)執(zhí)行的事務(wù)彼此無法看到對(duì)方的中間狀態(tài);
持久性(Durable):事務(wù)完成后所做的改動(dòng)都會(huì)被持久化,即使發(fā)生災(zāi)難性的失敗。通過日志和同步備份可以在故障發(fā)生后重建數(shù)據(jù)。
補(bǔ)充:關(guān)于事務(wù),在面試中被問到的概率是很高的,可以問的問題也是很多的。首先需要知道的是,只有存在并發(fā)數(shù)據(jù)訪問時(shí)才需要事務(wù)。當(dāng)多個(gè)事務(wù)訪問同一數(shù)據(jù)時(shí),可能會(huì)存在 5 類問題,包括 3 類數(shù)據(jù)讀取問題(臟讀、不可重復(fù)讀和幻讀)和 2 類數(shù)據(jù)更新問題(第 1 類丟失更新和第 2 類丟失更新)。臟讀(Dirty Read):A 事務(wù)讀取 B 事務(wù)尚未提交的數(shù)據(jù)并在此基礎(chǔ)上操作,而 B事務(wù)執(zhí)行回滾,那么 A 讀取到的數(shù)據(jù)就是臟數(shù)據(jù)。
時(shí)間 | 轉(zhuǎn)賬事務(wù) A | 取款事務(wù) B |
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為 1000 元 | |
T4 | 取出 500 元余額修改為 500 元 | |
T5 | 查詢賬戶余額為 500 元(臟讀) | |
T6 | 撤銷事務(wù)余額恢復(fù)為 1000 元 | |
T7 | 匯入 100 元把余額修改為 600 元 | |
T8 | 提交事務(wù) |
不可重復(fù)讀(Unrepeatable Read):事務(wù) A 重新讀取前面讀取過的數(shù)據(jù),發(fā)現(xiàn)該數(shù)據(jù)已經(jīng)被另一個(gè)已提交的事務(wù) B 修改過了。
時(shí)間 | 轉(zhuǎn)賬事務(wù) A | 取款事務(wù) B |
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為 1000 元 | |
T4 | 查詢賬戶余額為 1000 元 | |
T5 | 取出 100 元修改余額為 900 元 | |
T6 | 提交事務(wù) | |
T7 | 查詢賬戶余額為 900 元(不可重復(fù)讀) |
幻讀(Phantom Read):事務(wù) A 重新執(zhí)行一個(gè)查詢,返回一系列符合查詢條件的行,發(fā)現(xiàn)其中插入了被事務(wù) B 提交的行。
時(shí)間 | 轉(zhuǎn)賬事務(wù) A | 取款事務(wù) B |
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 統(tǒng)計(jì)總存款為 10000 元 | |
T4 | 新增一個(gè)存款賬戶存入 100 元 | |
T5 | 提交事務(wù) | |
T6 | 再次統(tǒng)計(jì)總存款為 10100 元(幻讀) |
第 1 類丟失更新:事務(wù) A 撤銷時(shí),把已經(jīng)提交的事務(wù) B 的更新數(shù)據(jù)覆蓋了。
時(shí)間 | 轉(zhuǎn)賬事務(wù) A | 取款事務(wù) B |
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為 1000 元 | |
T4 | 查詢賬戶余額為 1000 元 | |
T5 | 匯入 100 元修改余額為 1100 元 | |
T6 | 提交事務(wù) | |
T7 | 取出 100 元將余額修改為 900 元 | |
T8 | 撤銷事務(wù) | |
T9 | 余額恢復(fù)為 1000 元(丟失更新) |
第 2 類丟失更新:事務(wù) A 覆蓋事務(wù) B 已經(jīng)提交的數(shù)據(jù),造成事務(wù) B 所做的操作丟失。
時(shí)間 | 轉(zhuǎn)賬事務(wù) A | 取款事務(wù) B |
T1 | 開始事務(wù) | |
T2 | 開始事務(wù) | |
T3 | 查詢賬戶余額為 1000 元 | |
T4 | 查詢賬戶余額為 1000 元 | |
T5 | 取出 100 元將余額修改為 900 元 | |
T6 | 提交事務(wù) | |
T7 | 匯入 100 元修改余額為 1100 元 | |
T8 | 提交事務(wù) | |
T9 | 余額恢復(fù)為 1100 元(丟失更新) |
數(shù)據(jù)并發(fā)訪問所產(chǎn)生的問題,在有些場(chǎng)景下可能是允許的,但是有些場(chǎng)景下可能就是致命的,數(shù)據(jù)庫(kù)通常會(huì)通過鎖機(jī)制來解決數(shù)據(jù)并發(fā)訪問問題,按鎖定對(duì)象不同可以分為表級(jí)鎖和行級(jí)鎖;按并發(fā)事務(wù)鎖定關(guān)系可以分為共享鎖和獨(dú)占鎖,具體的內(nèi)容大家可以自行查閱資料進(jìn)行了解。直接使用鎖是非常麻煩的,為此數(shù)據(jù)庫(kù)為用戶提供了自動(dòng)鎖機(jī)制,只要用戶指定會(huì)話的事務(wù)隔離級(jí)別,數(shù)據(jù)庫(kù)就會(huì)通過分析 SQL 語句然后為事務(wù)訪問的資源加上合適的鎖,此外,數(shù)據(jù)庫(kù)還會(huì)維護(hù)這些鎖通過各種手段提高系統(tǒng)的性能,這些對(duì)用戶來說都是透明的(就是說你不用理解,事實(shí)上我確實(shí)也不知道)。ANSI/ISOSQL 92 標(biāo)準(zhǔn)定義了 4 個(gè)等級(jí)的事務(wù)隔離級(jí)別,如下表所示:
隔離級(jí)別 | 臟讀 | 不可重復(fù)讀 | 幻讀 | 第一類丟失更新 | 第二類丟失更新 |
READ UNCOMMITED | 允許 | 允許 | 允許 | 不允許 | 允許 |
READ COMMITTED | 不允許 | 允許 | 允許 | 不允許 | 允許 |
REPEATABLE READ | 不允許 | 不允許 | 允許 | 不允許 | 不允許 |
SERIALIZABLE | 不允許 | 不允許 | 不允許 | 不允許 | 不允許 |
????????需要說明的是,事務(wù)隔離級(jí)別和數(shù)據(jù)訪問的并發(fā)性是對(duì)立的,事務(wù)隔離級(jí)別越高并發(fā)性就越差。所以要根據(jù)具體的應(yīng)用來確定合適的事務(wù)隔離級(jí)別,這個(gè)地方?jīng)]有萬能的原則。
81、JDBC 中如何進(jìn)行事務(wù)處理?
????????Connection 提供了事務(wù)處理的方法,通過調(diào)用 setAutoCommit(false)可以設(shè)置手動(dòng)提交事務(wù);當(dāng)事務(wù)完成后用 commit()顯式提交事務(wù);如果在事務(wù)處理過程中發(fā)生異常則通過 rollback()進(jìn)行事務(wù)回滾。除此之外,從 JDBC 3.0 中還引入了Savepoint(保存點(diǎn))的概念,允許通過代碼設(shè)置保存點(diǎn)并讓事務(wù)回滾到指定的保存點(diǎn)。
要想了解更多:
千題千解·Java面試寶典_時(shí)光の塵的博客-CSDN博客