第1章:JDBC概述
1.1 數據的持久化
-
持久化(persistence):把數據保存到可掉電式存儲設備中以供之后使用。大多數情況下,特別是企業級應用,數據持久化意味着將內存中的數據保存到硬盤上加以”固化”,而持久化的實現過程大多通過各種關系數據庫來完成。
-
持久化的主要應用是將內存中的數據存儲在關系型數據庫中,當然也可以存儲在磁盤文件、XML數據文件中。
1.2 Java中的數據存儲技術
-
在Java中,數據庫存取技術可分為如下幾類:
-
JDBC直接訪問數據庫
-
JDO (Java Data Object )技術
-
第三方O/R工具,如Hibernate, Mybatis 等
-
-
JDBC是java訪問數據庫的基石,JDO、Hibernate、MyBatis等只是更好的封裝了JDBC。
1.3 JDBC介紹
-
JDBC(Java Database Connectivity)是一個獨立於特定數據庫管理系統、通用的SQL數據庫存取和操作的公共接口(一組API),定義了用來訪問數據庫的標准Java類庫,(java.sql,javax.sql)使用這些類庫可以以一種標准的方法、方便地訪問數據庫資源。
-
JDBC為訪問不同的數據庫提供了一種統一的途徑,為開發者屏蔽了一些細節問題。
-
JDBC的目標是使Java程序員使用JDBC可以連接任何提供了JDBC驅動程序的數據庫系統,這樣就使得程序員無需對特定的數據庫系統的特點有過多的了解,從而大大簡化和加快了開發過程。
-
如果沒有JDBC,那么Java程序訪問數據庫時是這樣的:
-
有了JDBC,Java程序訪問數據庫時是這樣的:
-
總結如下:
1.4 JDBC體系結構
-
JDBC接口(API)包括兩個層次:
-
面向應用的API:Java API,抽象接口,供應用程序開發人員使用(連接數據庫,執行SQL語句,獲得結果)。
-
面向數據庫的API:Java Driver API,供開發商開發數據庫驅動程序用。
-
JDBC是sun公司提供一套用於數據庫操作的接口,java程序員只需要面向這套接口編程即可。
不同的數據庫廠商,需要針對這套接口,提供不同實現。不同的實現的集合,即為不同數據庫的驅動。 ————面向接口編程
1.5 JDBC程序編寫步驟
補充:ODBC(Open Database Connectivity,開放式數據庫連接),是微軟在Windows平台下推出的。使用者在程序中只需要調用ODBC API,由 ODBC 驅動程序將調用轉換成為對特定的數據庫的調用請求。
第2章:獲取數據庫連接
2.1 要素一:Driver接口實現類
2.1.1 Driver接口介紹
-
java.sql.Driver 接口是所有 JDBC 驅動程序需要實現的接口。這個接口是提供給數據庫廠商使用的,不同數據庫廠商提供不同的實現。
-
在程序中不需要直接去訪問實現了 Driver 接口的類,而是由驅動程序管理器類(java.sql.DriverManager)去調用這些Driver實現。
-
Oracle的驅動:oracle.jdbc.driver.OracleDriver
-
mySql的驅動: com.mysql.jdbc.Driver
-
-
將上述jar包拷貝到Java工程的一個目錄中,習慣上新建一個lib文件夾。
在驅動jar上右鍵-->Build Path-->Add to Build Path
注意:如果是Dynamic Web Project(動態的web項目)話,則是把驅動jar放到WebContent(有的開發工具叫WebRoot)目錄中的WEB-INF目錄中的lib目錄下即可
2.1.2 加載與注冊JDBC驅動
-
加載驅動:加載 JDBC 驅動需調用 Class 類的靜態方法 forName(),向其傳遞要加載的 JDBC 驅動的類名
-
Class.forName(“com.mysql.jdbc.Driver”);
-
-
注冊驅動:DriverManager 類是驅動程序管理器類,負責管理驅動程序
-
使用DriverManager.registerDriver(com.mysql.jdbc.Driver)來注冊驅動
-
通常不用顯式調用 DriverManager 類的 registerDriver() 方法來注冊驅動程序類的實例,因為 Driver 接口的驅動程序類都包含了靜態代碼塊,在這個靜態代碼塊中,會調用 DriverManager.registerDriver() 方法來注冊自身的一個實例。下圖是MySQL的Driver實現類的源碼:
-
2.2 要素二:URL
-
JDBC URL 用於標識一個被注冊的驅動程序,驅動程序管理器通過這個 URL 選擇正確的驅動程序,從而建立到數據庫的連接。
-
JDBC URL的標准由三部分組成,各部分間用冒號分隔。
-
jdbc:子協議:子名稱
-
協議:JDBC URL中的協議總是jdbc
-
子協議:子協議用於標識一個數據庫驅動程序
-
子名稱:一種標識數據庫的方法。子名稱可以依不同的子協議而變化,用子名稱的目的是為了定位數據庫提供足夠的信息。包含主機名(對應服務端的ip地址),端口號,數據庫名
-
-
舉例:
-
幾種常用數據庫的 JDBC URL
-
MySQL的連接URL編寫方式:
-
jdbc:mysql://主機名稱:mysql服務端口號/數據庫名稱?參數=值&參數=值
-
jdbc:mysql://localhost:3306/atguigu
-
jdbc:mysql://localhost:3306/atguigu?useUnicode=true&characterEncoding=utf8(如果JDBC程序與服務器端的字符集不一致,會導致亂碼,那么可以通過參數指定服務器端的字符集)
-
jdbc:mysql://localhost:3306/atguigu?user=root&password=123456
-
-
Oracle 9i的連接URL編寫方式:
-
jdbc:oracle:thin:@主機名稱:oracle服務端口號:數據庫名稱
-
jdbc:oracle:thin:@localhost:1521:atguigu
-
-
SQLServer的連接URL編寫方式:
-
jdbc:sqlserver://主機名稱:sqlserver服務端口號:DatabaseName=數據庫名稱
-
jdbc:sqlserver://localhost:1433:DatabaseName=atguigu
-
-
2.3 要素三:用戶名和密碼
-
user,password可以用“屬性名=屬性值”方式告訴數據庫
-
可以調用 DriverManager 類的 getConnection() 方法建立到數據庫的連接
2.4 數據庫連接方式舉例
2.4.1 連接方式一
說明:上述代碼中顯式出現了第三方數據庫的API
2.4.2 連接方式二
說明:相較於方式一,這里使用反射實例化Driver,不在代碼中體現第三方數據庫的API。體現了面向接口編程思想。
2.4.3 連接方式三
說明:使用DriverManager實現數據庫的連接。體會獲取連接必要的4個基本要素。
2.4.4 連接方式四
說明:不必顯式的注冊驅動了。因為在DriverManager的源碼中已經存在靜態代碼塊,實現了驅動的注冊。
2.4.5 連接方式五(最終版)
其中,配置文件聲明在工程的src目錄下:【jdbc.properties】
user=root
password=abc123
url=jdbc:mysql://localhost:3306/test
driverClass=com.mysql.jdbc.Driver
說明:使用配置文件的方式保存配置信息,在代碼中加載配置文件
使用配置文件的好處:
①實現了代碼和數據的分離,如果需要修改配置信息,直接在配置文件中修改,不需要深入代碼 ②如果修改了配置信息,省去重新編譯的過程。
第3章:使用PreparedStatement實現CRUD操作
3.1 操作和訪問數據庫
-
數據庫連接被用於向數據庫服務器發送命令和 SQL 語句,並接受數據庫服務器返回的結果。其實一個數據庫連接就是一個Socket連接。
-
在 java.sql 包中有 3 個接口分別定義了對數據庫的調用的不同方式:
-
Statement:用於執行靜態 SQL 語句並返回它所生成結果的對象。
-
PrepatedStatement:SQL 語句被預編譯並存儲在此對象中,可以使用此對象多次高效地執行該語句。
-
CallableStatement:用於執行 SQL 存儲過程
-
3.2 使用Statement操作數據表的弊端
-
通過調用 Connection 對象的 createStatement() 方法創建該對象。該對象用於執行靜態的 SQL 語句,並且返回執行結果。
-
Statement 接口中定義了下列方法用於執行 SQL 語句:
int excuteUpdate(String sql):執行更新操作INSERT、UPDATE、DELETE
ResultSet executeQuery(String sql):執行查詢操作SELECT -
但是使用Statement操作數據表存在弊端:
-
問題一:存在拼串操作,繁瑣
-
問題二:存在SQL注入問題
-
-
SQL 注入是利用某些系統沒有對用戶輸入的數據進行充分的檢查,而在用戶輸入數據中注入非法的 SQL 語句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,從而利用系統的 SQL 引擎完成惡意行為的做法。
-
對於 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(從Statement擴展而來) 取代 Statement 就可以了。
-
代碼演示:
public class StatementTest {
// 使用Statement的弊端:需要拼寫sql語句,並且存在SQL注入的問題