JDBC高階編程
JDBC背景原理
背景
JDBC是Java應用程序訪問數據庫的里程碑式解決方案。Java研發者希望用相同的方式訪問不同的數據庫,以實現與具體數據庫無關的Java操作界面。
JDBC定義了一套標準接口,即訪問數據庫的通用API,不同的數據庫廠商根據各自數據庫的特點去實現這些接口。
JDBC(Java DataBase Connectivity)就是Java數據庫連接,說白了就是用Java語言來操作數據庫。原來我們操作數據庫是在控制檯使用SQL語句來操作數據庫,JDBC是用Java語言向數據庫發送SQL語句。
早期SUN公司的天才們想編寫一套可以連接天下所有數據庫的API,但是當他們剛剛開始時就發現這是不可完成的任務,因爲各個廠商的數據庫服務器差異太大了。後來SUN開始與數據庫廠商們討論,最終得出的結論是,由SUN提供一套訪問數據庫的規範(就是一組接口),並提供連接數據庫的協議標準,然後各個數據庫廠商會遵循SUN的規範提供一套訪問自己公司的數據庫服務器的API出現。SUN提供的規範命名爲JDBC,而各個廠商提供的,遵循了JDBC規範的,可以訪問自己數據庫的API被稱之爲驅動!
原理
JDBC是接口,而JDBC驅動纔是接口的實現,沒有驅動無法完成數據庫連接!每個數據庫廠商都有自己的驅動,用來連接自己公司的數據庫。
基本原理
架構原理
JDBC基本編輯
package com.test.spring.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class test {
// JDBC驅動
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
// 數據庫的賬戶密碼
static final String USER = "root";
static final String PASS = "123456";
static ResultSet rs = null;
public static void main(String[] args) throws SQLException {
// 第一步,加載一個Driver驅動
try {
Class.forName(JDBC_DRIVER);
} catch (ClassNotFoundException e) {
// 這裏會發生類沒有找到的異常
e.printStackTrace();
}
try {
// 第二步,創建數據庫連接
Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);
// 第三步,創建SQL命令發送器statement
Statement statement = connection.createStatement();
String sql = "SELECT * FROM tb_student";
// 第四步,通過statement發送SQL命令並得到結果
rs = statement.executeQuery(sql);
while (rs.next()) {
// 第五步,處理結果
String id = rs.getString("id");
System.out.println(id);
}
// 第六步,關閉數據庫資源
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
// 這裏會發生SQL異常,因爲我們提供的賬戶和密碼不一定能連接成功
} finally {
rs.close();
}
}
}
JDBC核心API
JDBC核心類(接口)介紹
1、Driver接口:表示java驅動程序接口。所有的具體的數據庫廠商要來實現此接口。
2、DriverManager類:驅動管理器類,用於管理所有註冊的驅動程序。
3、Connection接口:表示java程序和數據庫的連接對象。
4、Statement接口: 用於執行靜態的sql語句。
5、ResultSet接口:用於封裝查詢出來的數據。
Driver(驅動)
所謂的驅動,其實就是實現了java.sql.Driver接口的類。如oracle的驅動類是 oracle.jdbc.driver.OracleDriver.class(此類可以在oracle提供的JDBC jar包中找到),此類實現了java.sql.Driver接口。
由於驅動本質上還是一個class,將驅動加載到內存和加載普通的class原理是一樣的:使用Class.forName(“driverName”)。
// 加載Oracle數據庫驅動
class.forName("oracle.jdbc.Driver.OracleDriver");
// 加載SQL Server數據庫驅動
class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 加載MySQL數據庫驅動
class.forName("com.mysql.jdbc.Driver");
注意:Class.forName()將對應的驅動類加載到內存中,然後執行內存中的static靜態代碼段,代碼段中,會創建一個驅動Driver的實例,放入DriverManager中,供DriverManager使用。
DriverManager(驅動管理器類)
一般我們操作Driver,獲取Connection對象都是交給DriverManager統一管理的。DriverManger可以註冊和刪除加載的驅動程序,可以根據給定的url獲取符合url協議的驅動Driver或者是建立Conenction連接,進行數據庫交互。
More Actionsstatic void | deregisterDriver(Driver driver) 從DriverManager的列表中刪除一個驅動程序 |
---|---|
static Connection | getConnection(String url) 試圖建立到給定數據庫URL的連接 |
static Connection | getConnection(String url,Properties info) 試圖建立到給定數據庫URL的連接 |
static Connection | getConnection(String url,String user,String password) 試圖建立到給定數據庫URL的連接 |
static Driver | getDriver(String url) 試圖查找能理解給定URL的驅動程序 |
static Enumeration | getDrivers() 獲取帶有當前調用者可以訪問的所有當前已加載JDBC驅動程序的Enumerate |
static void | registerDriver(Driver driver) 向DriverManager註冊給定驅動程序 |
Connection(鏈接對象)
創建 Connection 連接對象,可以使用驅動Driver的 connect(url,props),也可以使用 DriverManager 提供的getConnection()方法,此方法通過url自動匹配對應的驅動Driver實例,然後調用對應的connect方法返回Connection對象實例。
Driver driver = DriverManager.getDriver(url);
Connection connection = driver.connect(url, props);
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, props);
ConnectionPool(鏈接池)
對於一個簡單的數據庫應用,由於對於數據庫的訪問不是很頻繁。這時可以簡單地在需要訪問數據庫時,就新創建一個連接,用完後就關閉它,這樣做也不會帶來什麼明顯的性能上的開銷。但是對於一個複雜的數據庫應用,情況就完全不同了。頻繁的建立、關閉連接,會極大的減低系統的性能,因爲對於連接的使用成了系統性能的瓶頸。
對於共享資源,有一個很著名的設計模式:資源池。該模式正是爲了解決資源頻繁分配、釋放所造成的問題的。把該模式應用到數據庫連接管理領域,就是建立一個數據庫連接池,提供一套高效的連接分配、使用策略,最終目標是實現連接的高效、安全的複用。
Statement接口
Statement接口用來處理髮送到數據庫的SQL語句對象,通過Connection對象創建。主要有三個常用方法:
Statement stmt=conn.createStatement();
// 1.execute方法,
// 如果執行的sql是查詢語句且有結果集則返回true,
// 如果是非查詢語句或者沒有結果集,返回false
boolean flag = stmt.execute(sql);
// 2.執行查詢語句,返回結果集
ResultSetrs = stmt.executeQuery(sql);
// 3.執行DML語句,返回影響的記錄數
int flag = stmt.executeUpdate(sql);
ResultSet接口
執行查詢SQL語句後返回的結果集,由ResultSet接口接收。ResultSet代表SQL查詢結果,其內部維護了一個讀取數據的遊標,默認情況在,遊標在第一行數據之前, 當調用next() 方法時候, 遊標會向下移動,並將返回結果集中是否包含數據, 如果包含數據就返回true. 結果集還提供了很好getXXX方法用於獲取結果集遊標指向當前行數據。
JDBC事務管理
事務(Transaction)是併發控制的基本單位,指作爲單個邏輯工作單元執行的系列操作,而這些邏輯工作單元需要滿足ACD特性。
- 原子性:atomicity
- 一致性:consistency
- 隔離性:isolation
- 持久性:durability
Connection
- .setAutoCommit() 開啓事務
- .commit() 提交事務
- .rollback() 回滾事務
原子性:該操作是最小邏輯單元整體,已經不可分隔。一致性:要麼所有都執行,要麼所有都不執行。隔離性:多個事務相互隔離,互不影響。持久性:事物的執行結果永久生效。
在JDBC中可以調用Connection對象的setAutoCommit(false)這個接口,將commit()之前的所有操作都看成是一個事物。同時,如果事務執行過程中發生異常,可以調用rollback()接口進行回滾到事務開始之前的狀態。
DAO模式
什麼是DAO?
Data Access Objects :數據存儲對象
DAO指位於業務邏輯和持久化數據之間實現對持久化數據的訪問,也就是將數據庫操作都封裝起來,對外提供相應的接口
採用面向接口,有利於代碼的,低耦合高類聚原則
DAO的優勢?
隔離業務邏輯代碼和數據訪問代碼
隔離不同數據庫實現
DAO的組成?
DAO接口:把對數據庫的所有操作定義爲抽象方法
DAO實現類:不同數據庫給出的DAO接口定義方法的具體實現
實體類:用於存放和傳輸對象數據
數據庫連接和關閉工具:避免了數據庫連接和關閉代碼的重複
總結
1、一個DAO工廠類;
2、一個DAO接口;
3、一個實現DAO接口的具體類;
4、 數據傳遞對象(實體對象(Entity)或值對象(Value Object,簡稱VO))