JDBC常見面試題集錦(二)

  JDBC的保存點(Savepoint)是什麼,如何使用?

  有時候事務包含了一組語句,而我們希望回滾到這個事務的某個特定的點。JDBC的保存點可以用來生成事務的一個檢查點,使得事務可以回滾到這個檢查點。

  一旦事務提交或者回滾了,它生成的任何保存點都會自動釋放並失效。回滾事務到某個特定的保存點後,這個保存點後所有其它的保存點會自動釋放並且失效。可以讀下這個瞭解更多關於JDBC Savepoint的信息。

20140319133019681108.JPG

  JDBC的DataSource是什麼,有什麼好處?

  DataSource即數據源,它是定義在javax.sql中的一個接口,跟DriverManager相比,它的功能要更強大。我們可以用它來創建數據庫連接,當然驅動的實現類會實際去完成這個工作。除了能創建連接外,它還提供瞭如下的特性:

  • 緩存PreparedStatement以便更快的執行

  • 可以設置連接超時時間

  • 提供日誌記錄的功能

  • ResultSet大小的最大閾值設置

  • 通過JNDI的支持,可以爲servlet容器提供連接池的功能

  關於JDBC數據源的示例請看下這裏

  如何通過JDBC的DataSource和Apache Tomcat的JNDI來創建連接池?

  對部署在servlet容器中的WEB程序而言,創建數據庫連接池非常簡單,僅需要以下幾步。

  • 在容器的配置文件中創建JDBC的JNDI資源,通常在server.xml或者context.xml裏面。像這樣:

    <Resource name="jdbc/MyDB"
          global="jdbc/MyDB"
          auth="Container"
          type="javax.sql.DataSource"
          driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/UserDB"
          username="pankaj"
          password="pankaj123"
          maxActive="100"
          maxIdle="20"
          minIdle="5"
          maxWait="10000"/>
    
    <ResourceLink name="jdbc/MyLocalDB"
                    global="jdbc/MyDB"
                    auth="Container"
                    type="javax.sql.DataSource" />
    


  • 在WEB應用程序中,先用InitialContext來查找JNDI資源,然後獲取連接。

    Context ctx = new InitialContext();
    DataSource ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/MyLocalDB");
    
    完整的示例請看這裏


  Apache的DBCP是什麼?

  如果用DataSource來獲取連接的話,通常獲取連接的代碼和驅動特定的DataSource是緊耦合的。另外,除了選擇DataSource的實現類,剩下的代碼基本都是一樣的。

  Apache的DBCP就是用來解決這些問題的,它提供的DataSource實現成爲了應用程序和不同JDBC驅動間的一個抽象層。Apache的DBCP庫依賴commons-pool庫,所以要確保它們都在部署路徑下。

  完整的使用示例請看這裏

  什麼是數據庫的隔離級別?

  當我們爲了數據的一致性使用事務時,數據庫系統用鎖來防止別人訪問事務中用到的數據。數據庫通過鎖來防止髒讀,不可重複讀(Non-Repeatable Reads)及幻讀(Phantom-Read)的問題。

  數據庫使用JDBC設置的隔離級別來決定它使用何種鎖機制,我們可以通過Connection的getTransactionIsolation和setTransactionIsolation方法來獲取和設置數據庫的隔離級別。

隔離級別事務髒讀不可重複讀幻讀
TRANSACTION_NONE不支持不可用不可用不可用
TRANSACTION_READ_COMMITTED支持阻止允許允許
TRANSACTION_READ_UNCOMMITTED支持允許允許允許
TRANSACTION_REPEATABLE_READ支持阻止阻止允許
TRANSACTION_SERIALIZABLE支持阻止阻止阻止

  JDBC的RowSet是什麼,有哪些不同的RowSet?

  RowSet用於存儲查詢的數據結果,和ResultSet相比,它更具靈活性。RowSet繼承自ResultSet,因此ResultSet能幹的,它們也能,而ResultSet做不到的,它們還是可以。RowSet接口定義在javax.sql包裏。

  RowSet提供的額外的特性有:

  • 提供了Java Bean的功能,可以通過settter和getter方法來設置和獲取屬性。RowSet使用了JavaBean的事件驅動模型,它可以給註冊的組件發送事件通知,比如遊標的移動,行的增刪改,以及RowSet內容的修改等。

  • RowSet對象默認是可滾動,可更新的,因此如果數據庫系統不支持ResultSet實現類似的功能,可以使用RowSet來實現。

  RowSet分爲兩大類:

  A. 連接型RowSet——這類對象與數據庫進行連接,和ResultSet很類似。JDBC接口只提供了一種連接型RowSet,javax.sql.rowset.JdbcRowSet,它的標準實現是com.sun.rowset.JdbcRowSetImpl。 B. 離線型RowSet——這類對象不需要和數據庫進行連接,因此它們更輕量級,更容易序列化。它們適用於在網絡間傳遞數據。有四種不同的離線型RowSet的實現。

  • CachedRowSet——可以通過他們獲取連接,執行查詢並讀取ResultSet的數據到RowSet裏。我們可以在離線時對數據進行維護和更新,然後重新連接到數據庫裏,並回寫改動的數據。

  • WebRowSet繼承自CachedRowSet——他可以讀寫XML文檔。

  • JoinRowSet繼承自WebRowSet——它不用連接數據庫就可以執行SQL的join操作。

  • FilteredRowSet繼承自WebRowSet——我們可以用它來設置過濾規則,這樣只有選中的數據纔可見。

  RowSet和ResultSet的區別是什麼?

  RowSet繼承自ResultSet,因此它有ResultSet的全部功能,同時它自己添加了些額外的特性。RowSet一個最大的好處是它可以是離線的,這樣使得它更輕量級,同時便於在網絡間進行傳輸。

  具體使用哪個取決於你的需求,不過如果你操作ResultSet對象的時間較長的話,最好選擇一個離線的RowSet,這樣可以釋放數據庫連接。

  常見的JDBC異常有哪些?

  有以下這些:

  • java.sql.SQLException——這是JDBC異常的基類。

  • java.sql.BatchUpdateException——當批處理操作執行失敗的時候可能會拋出這個異常。這取決於具體的JDBC驅動的實現,它也可能直接拋出基類異常java.sql.SQLException。

  • java.sql.SQLWarning——SQL操作出現的警告信息。

  • java.sql.DataTruncation——字段值由於某些非正常原因被截斷了(不是因爲超過對應字段類型的長度限制)。

  JDBC裏的CLOB和BLOB數據類型分別代表什麼?

  CLOB意思是Character Large OBjects,字符大對象,它是由單字節字符組成的字符串數據,有自己專門的代碼頁。這種數據類型適用於存儲超長的文本信息,那些可能會超出標準的VARCHAR數據類型長度限制(上限是32KB)的文本。

  BLOB是Binary Larget OBject,它是二進制大對象,由二進制數據組成,沒有專門的代碼頁。它能用於存儲超過VARBINARY限制(32KB)的二進制數據。這種數據類型適合存儲圖片,聲音,圖形,或者其它業務程序特定的數據。

  JDBC的髒讀是什麼?哪種數據庫隔離級別能防止髒讀?

  當我們使用事務時,有可能會出現這樣的情況,有一行數據剛更新,與此同時另一個查詢讀到了這個剛更新的值。這樣就導致了髒讀,因爲更新的數據還沒有進行持久化,更新這行數據的業務可能會進行回滾,這樣這個數據就是無效的。

  數據庫的TRANSACTIONREADCOMMITTED,TRANSACTIONREPEATABLEREAD,和TRANSACTION_SERIALIZABLE隔離級別可以防止髒讀。

  什麼是兩階段提交?

  當我們在分佈式系統上同時使用多個數據庫時,這時候我們就需要用到兩階段提交協議。兩階段提交協議能保證是分佈式系統提交的原子性。在第一個階段,事務管理器發所有的事務參與者發送提交的請求。如果所有的參與者都返回OK,它會向參與者正式提交該事務。如果有任何一個參與方返回了中止消息,事務管理器會回滾所有的修改動作。

  JDBC中存在哪些不同類型的鎖?

  從廣義上講,有兩種鎖機制來防止多個用戶同時操作引起的數據損壞。

  樂觀鎖——只有當更新數據的時候纔會鎖定記錄。 悲觀鎖——從查詢到更新和提交整個過程都會對數據記錄進行加鎖。

  不僅如此,一些數據庫系統還提供了行鎖,表鎖等鎖機制。

  DDL和DML語句分別代表什麼?

  DDL(數據定義語言,Data Definition Language)語句用來定義數據庫模式。Create,Alter, Drop, Truncate, Rename都屬於DDL語句,一般來說,它們是不返回結果的。

  DML(數據操作語言,Data Manipulation Language)語句用來操作數據庫中的數據。select, insert, update, delete, call等,都屬於DML語句。

  java.util.Date和java.sql.Date有什麼區別?

  java.util.Date包含日期和時間,而java.sql.Date只包含日期信息,而沒有具體的時間信息。如果你想把時間信息存儲在數據庫裏,可以考慮使用Timestamp或者DateTime字段。

  如何把圖片或者原始數據插入到數據庫中?

  可以使用BLOB類型將圖片或者原始的二進制數據存儲到數據庫裏。

  什麼是幻讀,哪種隔離級別可以防止幻讀?

  幻讀是指一個事務多次執行一條查詢返回的卻是不同的值。假設一個事務正根據某個條件進行數據查詢,然後另一個事務插入了一行滿足這個查詢條件的數據。之後這個事務再次執行了這條查詢,返回的結果集中會包含剛插入的那條新數據。這行新數據被稱爲幻行,而這種現象就叫做幻讀。

  只有TRANSACTION_SERIALIZABLE隔離級別才能防止產生幻讀。

  SQLWarning是什麼,在程序中如何獲取SQLWarning?

  SQLWarning是SQLException的子類,通過Connection, Statement, Result的getWarnings方法都可以獲取到它。 SQLWarning不會中斷查詢語句的執行,只是用來提示用戶存在相關的警告信息。

  如果Oracle的存儲過程的入參出參中包含數據庫對象,應該如何進行調用?

  如果Oracle的存儲過程的入參出參中包含數據庫對象,我們需要在程序創建一個同樣大小的對象數組,然後用它來生成Oracle的STRUCT對象。然後可以通過數據庫對象的setSTRUCT方法傳入這個struct對象,並對它進行使用。

  如果java.sql.SQLException: No suitable driver found該怎麼辦?

  如果你的SQL URL串格式不正確的話,就會拋出這樣的異常。不管是使用DriverManager還是JNDI數據源來創建連接都有可能拋出這種異常。它的異常棧看起來會像下面這樣。

org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class 'com.mysql.jdbc.Driver' for connect URL ''jdbc:mysql://localhost:3306/UserDB'
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1452)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
java.sql.SQLException: No suitable driver found for 'jdbc:mysql://localhost:3306/UserDB
    at java.sql.DriverManager.getConnection(DriverManager.java:604)
    at java.sql.DriverManager.getConnection(DriverManager.java:221)
    at com.journaldev.jdbc.DBConnection.getConnection(DBConnection.java:24)
    at com.journaldev.jdbc.DBConnectionTest.main(DBConnectionTest.java:15)
Exception in thread "main" java.lang.NullPointerException
    at com.journaldev.jdbc.DBConnectionTest.main(DBConnectionTest.java:16)

  解決這類問題的方法就是,檢查下日誌文件,像上面的這個日誌中,URL串是'jdbc:mysql://localhost:3306/UserDB,只要把它改成jdbc:mysql://localhost:3306/UserDB就好了。

  什麼是JDBC的最佳實踐?

  下面列舉了其中的一些:

  • 數據庫資源是非常昂貴的,用完了應該儘快關閉它。Connection, Statement, ResultSet等JDBC對象都有close方法,調用它就好了。

  • 養成在代碼中顯式關閉掉ResultSet,Statement,Connection的習慣,如果你用的是連接池的話,連接用完後會放回池裏,但是沒有關閉的ResultSet和Statement就會造成資源泄漏了。

  • 在finally塊中關閉資源,保證即便出了異常也能正常關閉。

  • 大量類似的查詢應當使用批處理完成。

  • 儘量使用PreparedStatement而不是Statement,以避免SQL注入,同時還能通過預編譯和緩存機制提升執行的效率。

  • 如果你要將大量數據讀入到ResultSet中,應該合理的設置fetchSize以便提升性能。

  • 你用的數據庫可能沒有支持所有的隔離級別,用之前先仔細確認下。

  • 數據庫隔離級別越高性能越差,確保你的數據庫連接設置的隔離級別是最優的。

  • 如果在WEB程序中創建數據庫連接,最好通過JNDI使用JDBC的數據源,這樣可以對連接進行重用。

  • 如果你需要長時間對ResultSet進行操作的話,儘量使用離線的RowSet。

  譯註:終於翻譯完了,希望能對你的面試有所幫助。拿個好offer!

轉載自:http://www.admin10000.com/document/4072.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章