JDBC概述 JDBC(Java Data Base Connectivity,java資料庫連接)是一種用於執行SQL語句的Java API,可以為多種關係資料庫提供統一訪問,它由一組用Java語言編寫的類和介面組成。是Java訪問資料庫的標準規範。 JDBC提供了一種基準,據此可以構建更高級的工 ...
目錄
JDBC概述
JDBC(Java Data Base Connectivity,java資料庫連接)是一種用於執行SQL語句的Java API,可以為多種關係資料庫提供統一訪問,它由一組用Java語言編寫的類和介面組成。是Java訪問資料庫的標準規範。
JDBC提供了一種基準,據此可以構建更高級的工具和介面,使資料庫開發人員能夠編寫資料庫應用程式。
JDBC需要連接驅動,驅動是兩個設備要進行通信,滿足一定通信數據格式,數據格式由設備提供商規定,設備提供商為設備提供驅動軟體,通過軟體可以與該設備進行通信。
JDBC原理
Java提供訪問資料庫規範稱為JDBC,而生產廠商提供規範的實現類稱為驅動。
JDBC是介面,驅動是介面的實現,沒有驅動將無法完成資料庫連接,從而不能操作資料庫!每個資料庫廠商都需要提供自己的驅動,用來連接自己公司的資料庫,也就是說驅動一般都由資料庫生成廠商提供。
JDBC開發步驟
Java資料庫鏈接主要包括以下幾步:
- 註冊驅動
- 獲得連接
- 獲得語句執行平臺
- 執行sql語句
- 處理結果
- 釋放資源
導入驅動包(jar包)(以eclipse為例)
在項目文件夾下創建lib目錄,用於存放當前項目需要的所有jar包(上面下載的jar包)選擇jar包,右鍵執行build path / Add to Build Path
註冊驅動
JDBC規範定義驅動介面java.sql.Driver,MySql驅動包提供了實現類com.mysql.jdbc.Driver、DriverManager工具類,提供註冊驅動的方法 registerDriver(),方法的參數是java.sql.Driver,所以我們可以通過如下語句進行註冊:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
但是並不提倡使用這種方法,原因如下:
通過查詢com.mysql.jdbc.Driver源碼,我們發現Driver類“主動”將自己進行註冊
*/
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
……
}
// 這樣會造成驅動被註冊兩次 而且這樣編碼不易於程式擴展和維護
通常開發我們使用Class.forName() 載入一個使用字元串描述的驅動類。
如果使用Class.forName()將類載入到記憶體,該類的靜態代碼將自動執行。
所以我們可以使用一下代碼來註冊驅動:
Class.forName("com.mysql.jdbc.Driver");
獲得連接
獲取連接需要方法 DriverManager.getConnection(url,username,password),三個參數分別表示,url 需要連接資料庫的位置(網址) username用戶名 password 密碼。
url比較複雜,下麵是mysql的url:
jdbc:mysql://localhost:3306/mydb
JDBC規定url的格式由三部分組成,每個部分中間使用冒號分隔。
第一部分是jdbc,這是固定的;
第二部分是資料庫名稱,那麼連接mysql資料庫,第二部分當然是mysql了;
第三部分是由資料庫廠商規定的,我們需要瞭解每個資料庫廠商的要求,mysql的第三部分分別由資料庫伺服器的IP地址(localhost)、埠號(3306),以及DATABASE名稱(mydb)組成。
代碼:Connection con = DriverManager.getConnection
(“jdbc:mysql://localhost:3306/mydb”,”root”,”root”);
獲得語句執行平臺
常用方法有以下三種:
- int executeUpdate(String sql); --執行insert update delete語句.
- ResultSet executeQuery(String sql); --執行select語句.
- boolean execute(String sql); --執行select返回true 執行其他的語句返回false.
String sql = "某SQL語句";
獲取Statement語句執行平臺:Statement stmt = con.createStatement();
結果處理
執行insert、update、delete無需處理
我們使用ResultSet來處理結果,ResultSet實際上就是一張二維的表格,我們可以調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,這時就可以使用ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的數據:
rs.next();//指向第一行
rs.getInt(1);//獲取第一行第一列的數據
常用方法有以下幾種:
- Object getObject(int index) / Object getObject(String name) 獲得任意對象
- String getString(int index) / Object getObject(String name) 獲得字元串
- int getInt(int index) / Object getObject(String name) 獲得整形
- double getDouble(int index) / Object getObject(String name) 獲得雙精度浮點型
釋放資源
與IO流一樣,使用後的東西都需要關閉!關閉的順序是先得到的後關閉,後得到的先關閉。
rs.close();
stmt.close();
con.close();
SQL 註入問題
假設有登錄案例SQL語句如下:
SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼;
此時,當用戶輸入正確的賬號與密碼後,查詢到了信息則讓用戶登錄。但是當用戶輸入的賬號為XXX 密碼為:XXX’ OR ‘a’=’a時,則真正執行的代碼變為:
SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’ OR ’a’=’a’;
此時,上述查詢語句時永遠可以查詢出結果的。那麼用戶就直接登錄成功了,顯然我們不希望看到這樣的結果,這便是SQL註入問題。
為此,我們使用PreparedStatement
來解決對應的問題。
預處理對象
使用PreparedStatement預處理對象時,建議每條sql語句所有的實際參數,都使用逗號分隔。
String sql = "insert into sort(sid,sname) values(?,?)";;
PreparedStatement預處理對象代碼:
PreparedStatement psmt = conn.prepareStatement(sql)
常用方法:
{% note info %} 執行SQL語句
int executeUpdate(); --執行insert update delete語句.
ResultSet executeQuery(); --執行select語句.
boolean execute(); --執行select返回true執行其他的語句返回false.
{% endnote %}
{% note warning %}
設置實際參數
void setXxx(int index,Xxxxx)將指定參數設置為給定Java的xx值。在將此值發送到資料庫時,驅動程式將它轉換成一個 SQL Xxx類型值。
{% endnote %}
預處理對象executeUpdate方法
通過預處理對象的executeUpdate方法,完成記錄的insertupdatedelete語句的執行。操作格式統一如下:
- 註冊驅動
- 獲取連接
- 獲取預處理對象
- SQL語句占位符設置實際參數
- 執行SQL語句
- 釋放資源
插入操作(insert)
實現向表中插入指定的新內容
public void demo01() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理對象
String sql = "insert into sort(sname) values(?)";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句占位符設置實際參數
stat.setString(1, "奢侈品");
// 5執行SQL語句
int line = stat.executeUpdate();
System.out.println("新添加記錄數:" + line);
// 6釋放資源
stat.close();
conn.close();
}
更新操作(update)
public void demo02() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理對象中
String sql = "update sort set sname=? where sid=?";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句占位符設置實際參數
stat.setString(1, "數位產品");
stat.setInt(2, 1);
// 5執行SQL語句
int line = stat.executeUpdate();
System.out.println("更新記錄數:" + line);
// 6釋放資源
stat.close();
conn.close();
}
刪除操作
public void demo03() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理對象
String sql = "delete from sort where sid=?";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句占位符設置實際參數
stat.setInt(1, 1);
// 5執行SQL語句
int line = stat.executeUpdate();
System.out.println("刪除記錄數:" + line);
// 6釋放資源
stat.close();
conn.close();
}
預處理對象executeQuery方法
通過預處理對象的executeQuery方法,完成記錄的select語句的執行。操作格式統一如下:
- 註冊驅動
- 獲取連接
- 獲取預處理對象
- SQL語句占位符設置實際參數
- 執行SQL語句
- 處理結果集(遍歷結果集合)
- 釋放資源
查詢操作
public void demo04() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理對象
String sql = "select * from sort";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句占位符設置實際參數
// 5執行SQL語句
ResultSet rs = stat.executeQuery();
// 6處理結果集(遍歷結果集合)
while( rs.next() ){
//獲取當前行的分類ID
String sid = rs.getString("sid");//方法參數為資料庫表中的列名
//獲取當前行的分類名稱
String sname = rs.getString("sname");
//顯示數據
System.out.println(sid+"-----"+sname);
}
// 7釋放資源
rs.close();
stat.close();
conn.close();
}
public void demo05() throws Exception {
// 1註冊驅動
Class.forName("com.mysql.jdbc.Driver");
// 2獲取連接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
// 3獲得預處理對象
String sql = "select * from sort where sname=?";
PreparedStatement stat = conn.prepareStatement(sql);
// 4 SQL語句占位符設置實際參數
stat.setString(1, "奢侈品");
// 5執行SQL語句
ResultSet rs = stat.executeQuery();
// 6處理結果集(遍歷結果集合)
while( rs.next() ){
//獲取當前行的分類ID
String sid = rs.getString("sid");//方法參數為資料庫表中的列名
//獲取當前行的分類名稱
String sname = rs.getString("sname");
//顯示數據
System.out.println(sid+"-----"+sname);
}
// 7釋放資源
rs.close();
stat.close();
conn.close();
}
JDBC工具類
“獲得資料庫連接”操作,將在以後的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連接對象的方法,從而達到代碼的重覆利用。
該工具類提供方法:public static Connection getConn ()。代碼如下:
/*
* JDBC工具類
*/
public class JDBCUtils {
public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
public static final String URL = "jdbc:mysql://localhost:3306/mydb";
public static final String USER = "root";
public static final String PASSWORD = "root";
static {
try {
Class.forName(DRIVERNAME);
} catch (ClassNotFoundException e) {
System.out.println("資料庫驅動註冊失敗!");
}
}
//提供獲取連接的方法
public static Connection getConn() throws Exception {
// 2. 獲得連接
Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
// 返回連接
return conn;
}
}
如圖片失效等問題,參閱公眾號文章:https://mp.weixin.qq.com/s/Nlmj6ObCdTeGCQXog_GBrw