JDBC常見面試題集錦

什麼是JDBC,在何時會用到它?

JDBC的全稱是Java DataBase Connection,也就是Java數據庫鏈接,咱們能夠用它來操做關係型數據庫。JDBC接口及相關類在java.sql包和javax.sql包裏。咱們能夠用它來鏈接數據庫,執行SQL查詢,存儲過程,並處理返回的結果。java

JDBC接口讓Java程序和JDBC驅動實現了鬆耦合,使得切換不一樣的數據庫變得更加簡單。mysql

有哪些不一樣類型的JDBC驅動?

有四類JDBC驅動。和數據庫進行交互的Java程序分紅兩個部分,一部分是JDBC的API,實際工做的驅動則是另外一部分。web

A JDBC-ODBC Bridge plus ODBC Driver(類型1):它使用ODBC驅動鏈接數據庫。須要安裝ODBC以便鏈接數據庫,正由於這樣,這種方式如今已經基本淘汰了。sql

B Native API partly Java technology-enabled driver(類型2):這種驅動把JDBC調用適配成數據庫的本地接口的調用。數據庫

C Pure Java Driver for Database Middleware(類型3):這個驅動把JDBC調用轉發給中間件服務器,由它去和不一樣的數據庫進行鏈接。用這種類型的驅動須要部署中間件服務器。這種方式增長了額外的網絡調用,致使性能變差,所以不多使用。apache

D Direct-to-Database Pure Java Driver(類型4):這個驅動把JDBC轉化成數據庫使用的網絡協議。這種方案最簡單,也適合經過網絡鏈接數據庫。不過使用這種方式的話,須要根據不一樣數據庫選用特定的驅動程序,好比OJDBC是Oracle開發的Oracle數據庫的驅動,而MySQL Connector/J是MySQL數據庫的驅動。數組

JDBC是如何實現Java程序和JDBC驅動的鬆耦合的?

JDBC API使用Java的反射機制來實現Java程序和JDBC驅動的鬆耦合。隨便看一個簡單的JDBC示例,你會發現全部操做都是經過JDBC接口完成的,而驅動只有在經過Class.forName反射機制來加載的時候纔會出現。緩存

我以爲這是Java核心庫裏反射機制的最佳實踐之一,它使得應用程序和驅動程序之間進行了隔離,讓遷移數據庫的工做變得更簡單。在這裏能夠看到更多JDBC的使用示例。tomcat

什麼是JDBC鏈接,在Java中如何建立一個JDBC鏈接?

JDBC鏈接是和數據庫服務器創建的一個會話。你能夠想像成是一個和數據庫的Socket鏈接。服務器

建立JDBC鏈接很簡單,只須要兩步:

A. 註冊並加載驅動:使用Class.forName(),驅動類就會註冊到DriverManager裏面並加載到內存裏。 B. 用DriverManager獲取鏈接對象:調用DriverManager.getConnnection()方法並傳入數據庫鏈接的URL,用戶名及密碼,就能獲取到鏈接對象。

 1 Connection con = null;
 2 try{
 3     // load the Driver Class
 4     Class.forName("com.mysql.jdbc.Driver");
 5     // create the connection now
 6     con = DriverManager.getConnection("jdbc:mysql://localhost:3306/DBName",
 7                     "username",
 8                     "password");
 9     }catch (SQLException e) {
10             System.out.println("Check database is UP and configs are correct");
11             e.printStackTrace();
12     }catch (ClassNotFoundException e) {
13             System.out.println("Please include JDBC MySQL jar in classpath");
14             e.printStackTrace();
15     }
16 }

 JDBC的DriverManager是用來作什麼的?

JDBC的DriverManager是一個工廠類,咱們經過它來建立數據庫鏈接。當JDBC的Driver類被加載進來時,它會本身註冊到DriverManager類裏面,你能夠看下JDBC Driver類的源碼來了解一下。

而後咱們會把數據庫配置信息傳成DriverManager.getConnection()方法,DriverManager會使用註冊到它裏面的驅動來獲取數據庫鏈接,並返回給調用的程序。

在Java程序中,如何獲取數據庫服務器的相關信息?

使用DatabaseMetaData能夠獲取到服務器的信息。當和數據庫的鏈接成功創建了以後,能夠經過調用getMetaData()方法來獲取數據庫的元信息。DatabaseMetaData裏面有不少方法,經過它們能夠獲取到數據庫的產品名稱,版本號,配置信息等。

DatabaseMetaData metaData = con.getMetaData();
String dbProduct = metaData.getDatabaseProductName();

JDBC的Statement是什麼?

Statement是JDBC中用來執行數據庫SQL查詢語句的接口。經過調用鏈接對象的getStatement()方法咱們能夠生成一個Statement對象。咱們能夠經過調用它的execute(),executeQuery(),executeUpdate()方法來執行靜態SQL查詢。

因爲SQL語句是程序中傳入的,若是沒有對用戶輸入進行校驗的話可能會引發SQL注入的問題,若是想了解更多關於SQL注入的,能夠看下這裏

默認狀況下,一個Statement同時只能打開一個ResultSet。若是想操做多個ResultSet對象的話,須要建立多個Statement。Statement接口的全部execute方法開始執行時都默認會關閉當前打開的ResultSet。

execute,executeQuery,executeUpdate的區別是什麼?

Statement的execute(String query)方法用來執行任意的SQL查詢,若是查詢的結果是一個ResultSet,這個方法就返回true。若是結果不是ResultSet,好比insert或者update查詢,它就會返回false。咱們能夠經過它的getResultSet方法來獲取ResultSet,或者經過getUpdateCount()方法來獲取更新的記錄條數。

Statement的executeQuery(String query)接口用來執行select查詢,而且返回ResultSet。即便查詢不到記錄返回的ResultSet也不會爲null。咱們一般使用executeQuery來執行查詢語句,這樣的話若是傳進來的是insert或者update語句的話,它會拋出錯誤信息爲 「executeQuery method can not be used for update」的java.util.SQLException。

Statement的executeUpdate(String query)方法用來執行insert或者update/delete(DML)語句,或者 什麼也不返回DDL語句。返回值是int類型,若是是DML語句的話,它就是更新的條數,若是是DDL的話,就返回0。

只有當你不肯定是什麼語句的時候才應該使用execute()方法,不然應該使用executeQuery或者executeUpdate方法。

JDBC的PreparedStatement是什麼?

PreparedStatement對象表明的是一個預編譯的SQL語句。用它提供的setter方法能夠傳入查詢的變量。

因爲PreparedStatement是預編譯的,經過它能夠將對應的SQL語句高效的執行屢次。因爲PreparedStatement自動對特殊字符轉義,避免了SQL注入攻擊,所以應當儘可能的使用它。

PreparedStatement中如何注入NULL值?

可使用它的setNull方法來把null值綁定到指定的變量上。setNull方法須要傳入參數的索引以及SQL字段的類型,像這樣:

ps.setNull(10, java.sql.Types.INTEGER);.

Statement中的getGeneratedKeys方法有什麼用?

有的時候表會生成主鍵,這時候就能夠用Statement的getGeneratedKeys()方法來獲取這個自動生成的主鍵的值了。

相對於Statement,PreparedStatement的優勢是什麼?

它和Statement相比優勢在於:

  • PreparedStatement有助於防止SQL注入,由於它會自動對特殊字符轉義。
  • PreparedStatement能夠用來進行動態查詢。
  • PreparedStatement執行更快。尤爲當你重用它或者使用它的拼量查詢接口執行多條語句時。
  • 使用PreparedStatement的setter方法更容易寫出面向對象的代碼,而Statement的話,咱們得拼接字符串來生成查詢語句。若是參數太多了,字符串拼接看起來會很是醜陋而且容易出錯。

PreparedStatement的缺點是什麼,怎麼解決這個問題?

PreparedStatement的一個缺點是,咱們不能直接用它來執行in條件語句;須要執行IN條件語句的話,下面有一些解決方案:

  • 分別進行單條查詢——這樣作性能不好,不推薦。
  • 使用存儲過程——這取決於數據庫的實現,不是全部數據庫都支持。
  • 動態生成PreparedStatement——這是個好辦法,可是不能享受PreparedStatement的緩存帶來的好處了。
  • 在PreparedStatement查詢中使用NULL值——若是你知道輸入變量的最大個數的話,這是個不錯的辦法,擴展一下還能夠支持無限參數。

關於這個問題更詳細的分析能夠看下這篇文章

JDBC的ResultSet是什麼?

在查詢數據庫後會返回一個ResultSet,它就像是查詢結果集的一張數據表。

ResultSet對象維護了一個遊標,指向當前的數據行。開始的時候這個遊標指向的是第一行。若是調用了ResultSet的next()方法遊標會下移一行,若是沒有更多的數據了,next()方法會返回false。能夠在for循環中用它來遍歷數據集。

默認的ResultSet是不能更新的,遊標也只能往下移。也就是說你只能從第一行到最後一行遍歷一遍。不過也能夠建立能夠回滾或者可更新的ResultSet,像下面這樣。

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);

 當生成ResultSet的Statement對象要關閉或者從新執行或是獲取下一個ResultSet的時候,ResultSet對象也會自動關閉。

能夠經過ResultSet的getter方法,傳入列名或者從1開始的序號來獲取列數據。

有哪些不一樣的ResultSet?

根據建立Statement時輸入參數的不一樣,會對應不一樣類型的ResultSet。若是你看下Connection的方法,你會發現createStatement和prepareStatement方法重載了,以支持不一樣的ResultSet和併發類型。

一共有三種ResultSet對象。

  • ResultSet.TYPE_FORWARD_ONLY:這是默認的類型,它的遊標只能往下移。
  • ResultSet.TYPE_SCROLL_INSENSITIVE:遊標能夠上下移動,一旦它建立後,數據庫裏的數據再發生修改,對它來講是透明的。
  • ResultSet.TYPE_SCROLL_SENSITIVE:遊標能夠上下移動,若是生成後數據庫還發生了修改操做,它是可以感知到的。

ResultSet有兩種併發類型。

  • ResultSet.CONCUR_READ_ONLY:ResultSet是隻讀的,這是默認類型。
  • ResultSet.CONCUR_UPDATABLE:咱們可使用ResultSet的更新方法來更新裏面的數據。

Statement中的setFetchSize和setMaxRows方法有什麼用處?

setMaxRows能夠用來限制返回的數據集的行數。固然經過SQL語句也能夠實現這個功能。好比在MySQL中咱們能夠用LIMIT條件來設置返回結果的最大行數。

setFetchSize理解起來就有點費勁了,由於你得知道Statement和ResultSet是怎麼工做的。當數據庫在執行一條查詢語句時,查詢到的數據是在數據庫的緩存中維護的。ResultSet其實引用的是數據庫中緩存的結果。

假設咱們有一條查詢返回了100行數據,咱們把fetchSize設置成了10,那麼數據庫驅動每次只會取10條數據,也就是說得取10次。當每條數據須要處理的時間比較長的時候而且返回數據又很是多的時候,這個可選的參數就變得很是有用了。

咱們能夠經過Statement來設置fetchSize參數,不過它會被ResultSet對象設置進來的值所覆蓋掉。

如何使用JDBC接口來調用存儲過程?

存儲過程就是數據庫編譯好的一組SQL語句,能夠經過JDBC接口來進行調用。咱們能夠經過JDBC的CallableStatement接口來在數據庫中執行存儲過程。初始化CallableStatement的語法是這樣的:

1 CallableStatement stmt = con.prepareCall("{call insertEmployee(?,?,?,?,?,?)}");
2 stmt.setInt(1, id);
3 stmt.setString(2, name);
4 stmt.setString(3, role);
5 stmt.setString(4, city);
6 stmt.setString(5, country);
7 //register the OUT parameter before calling the stored procedure
8 stmt.registerOutParameter(6, java.sql.Types.VARCHAR);
9 stmt.executeUpdate();

咱們得在執行CallableStatement以前註冊OUT參數。關於這個更詳細的資料能夠看這裏

JDBC的批處理是什麼,有什麼好處?

有時候相似的查詢咱們須要執行不少遍,好比從CSV文件中加載數據到關係型數據庫的表裏。咱們也知道,執行查詢能夠用Statement或者PreparedStatement。除此以外,JDBC還提供了批處理的特性,有了它,咱們能夠在一次數據庫調用中執行多條查詢語句。

JDBC經過Statement和PreparedStatement中的addBatch和executeBatch方法來支持批處理。

批處理比一條條語句執行的速度要快得多,由於它須要不多的數據庫調用,想進一步瞭解請點這裏

JDBC的事務管理是什麼,爲何須要它?

默認狀況下,咱們建立的數據庫鏈接,是工做在自動提交的模式下的。這意味着只要咱們執行完一條查詢語句,就會自動進行提交。所以咱們的每條查詢,實際上都是一個事務,若是咱們執行的是DML或者DDL,每條語句完成的時候,數據庫就已經完成修改了。

有的時候咱們但願由一組SQL查詢組成一個事務,若是它們都執行OK咱們再進行提交,若是中途出現異常了,咱們能夠進行回滾。

JDBC接口提供了一個setAutoCommit(boolean flag)方法,咱們能夠用它來關閉鏈接自動提交的特性。咱們應該在須要手動提交時才關閉這個特性,否則的話事務不會自動提交,每次都得手動提交。數據庫經過表鎖來管理事務,這個操做很是消耗資源。所以咱們應當完成操做後儘快的提交事務。在這裏有更多關於事務的示例程序。

如何回滾事務?

經過Connection對象的rollback方法能夠回滾事務。它會回滾此次事務中的全部修改操做,並釋放當前鏈接所持有的數據庫鎖。

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

 有時候事務包含了一組語句,而咱們但願回滾到這個事務的某個特定的點。JDBC的保存點能夠用來生成事務的一個檢查點,使得事務能夠回滾到這個檢查點。

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

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

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

  • 緩存PreparedStatement以便更快的執行
  • 能夠設置鏈接超時時間
  • 提供日誌記錄的功能
  • ResultSet大小的最大閾值設置
  • 經過JNDI的支持,能夠爲servlet容器提供鏈接池的功能

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

如何經過JDBC的DataSource和Apache Tomcat的JNDI來建立鏈接池?

對部署在servlet容器中的WEB程序而言,建立數據庫鏈接池很是簡單,僅須要如下幾步。

  • 在容器的配置文件中建立JDBC的JNDI資源,一般在server.xml或者context.xml裏面。像這樣:
     1 <Resource name="jdbc/MyDB"
     2       global="jdbc/MyDB"
     3       auth="Container"
     4       type="javax.sql.DataSource"
     5       driverClassName="com.mysql.jdbc.Driver"
     6       url="jdbc:mysql://localhost:3306/UserDB"
     7       username="pankaj"
     8       password="pankaj123"
     9       maxActive="100"
    10       maxIdle="20"
    11       minIdle="5"
    12       maxWait="10000"/>
    13 <ResourceLink name="jdbc/MyLocalDB"
    14       global="jdbc/MyDB"
    15       auth="Container"
    16       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。
相關文章
相關標籤/搜索