Driver接口:定義了一個驅動程序接口,每一個數據庫的JDBC driver都應該實現這個接口,用於訪問對應的數據庫。比如MySQL的driver為com.mysql.jdbc.Driver。Java SQL框架允許多個數據庫驅動程序。
DriverManager類:管理一組JDBC driver。DriverManager通過jdbcUrl,在classpath中加載相應數據庫的JDBC driver。當加載Driver類時,它會創建一個實例並將其本身注冊到DriverManager中。這樣,我們就可以通過DriverManager獲取到所有driver實例,並且可以通過jdbcUrl獲取到Driver及Connection實例。
Connection接口:與特定數據庫的連接(會話),用於創建及執行SQL語句(statements)並在連接的上下文中返回結果。注意:配置Connection時,JDBC應用程序應使用相應的Connection方法,例如setAutoCommit或setTransactionIsolation。當有可用的JDBC方法時,應用程序不應直接調用SQL命令來更改連接的配置。默認情況下,Connection對象處於自動提交(auto-commit)模式,這意味着它在執行每個語句后自動提交更改。如果已禁用自動提交模式,則必須顯式調用方法commit才能提交更改;否則,將無法保存數據庫更改。同一事務中所有的操作,都必須使用同一個Connection對象。
Statement接口:表示SQL語句的接口。需要用一個Connection對象來創建Statement對象。執行Statement對象,它們生成ResultSet對象,這是一個表示數據庫結果集的數據表。Connection可以創建以下3種Statement:
(1)Statement:用於執行不帶參數的簡單SQL語句。其中,有3種execute方法:
execute:執行任意SQL。如果執行返回的第一個對象是ResultSet對象,則返回true。通過調用statement.getResultSet來檢索從查詢返回的ResultSet對象。
executeQuery:執行一個能返回一個ResultSet對象的SQL。一般是查詢語句。
executeUpdate:返回一個整數,表示受SQL語句影響的行數。用於執行INSERT,UPDATE,DELETE等語句。
(2)PreparedStatement:(Extends Statement)用於預編譯可能包含輸入參數的SQL語句,並把預編譯后的sql語句存在對象中,那么這樣每次傳入參數執行SQL操作會變得更加高效。
(3)CallableStatement:(Extends PreparedStatement)執行可能包含輸入和輸出參數的存儲過程。
DataSource接口:作為DriverManager工具的替代方案,DataSource對象應該是獲取連接的首選方法。通常我們使用連接池的方式實現DataSource。如hikari,c3p0,dbcp2,tomcat等。由於數據庫連接是一種昂貴的資源,所以應該使用數據庫連接池負責分配、管理和釋放數據庫連接。連接池基本的思想是在系統初始化的時候,將數據庫連接作為對象存儲在內存中,當用戶需要訪問數據庫時,並非建立一個新的連接,而是從連接池中取出一個已建立的空閑連接對象。使用完畢后,用戶也並非將連接關閉,而是將連接放回連接池中,以供下一個請求訪問使用。而連接的建立、斷開都由連接池自身來管理。同時,還可以通過設置連接池的參數來控制連接池中的初始連接數、連接的上下限數以及每個連接的最大使用次數、最大空閑時間等等。也可以通過其自身的管理機制來監視數據庫連接的數量、使用情況等。
下面是一個是使用hikari數據庫連接池獲取Connection的例子:
String jdbcUrl = "jdbc:mysql://localhost:3306/test_db"; String username = "xxx"; String password = "xxx"; HikariConfig config = new HikariConfig(); config.setJdbcUrl(jdbcUrl); config.setUsername(username); config.setPassword(password); try (HikariDataSource datasource = new HikariDataSource(config); Connection conn = datasource.getConnection(); Statement stmt = conn.createStatement()) { conn.setAutoCommit(false); try { stmt.execute("INSERT INTO test(id, account) VALUES (1, 100)"); stmt.execute("INSERT INTO test(id, account) VALUES (2, 200)"); stmt.execute("INSERT INTO test(id, account) VALUES (3, 300)"); } catch (SQLException e) { e.printStackTrace(); conn.rollback(); // rollback throw e; } conn.commit(); // commit } catch (SQLException e) { e.printStackTrace(); throw new RuntimeException("Error occurred!"); }
jdbc:mysql://localhost:3306/test_db