Java 高階工程師進階之路 JDBC
JDBC介面及資料庫廠商實現
JDBC中定義了一些介面:
1、驅動管理:
DriverManager
2、連線介面
Connection
DatabasemetaData
3、語句物件介面
Statement
PreparedStatement
CallableStatement
4、結果集介面
ResultSet
ResultSetMetaData
JDBC工作原理
JDBC只定義介面,具體實現由各個資料庫廠商負責。
程式設計師使用時只需要呼叫介面,實際呼叫的是底層資料庫廠商的實現部分。
JDBC訪問資料庫的工作過程:
載入驅動,建立連線
建立語句物件
執行SQL語句
處理結果集
關閉連線
Driver介面及驅動類載入
要使用JDBC介面,需要先將對應資料庫的實現部分(驅動)載入進來。
驅動類載入方式(Oracle):
Class.forName("oracle.jdbc.driver.OracleDriver");
- 1
這條語句的含義是:裝載驅動類,驅動類通過static塊實現在DriverManager中的“自動註冊”。
Connection介面
Connection介面負責應用程式對資料庫的連線,在載入驅動之後,使用url、username、password三個引數,建立到具體資料庫的連線。
Class.forName("oracle.jdbc.OracleDriver")
//根據url連線引數,找到與之匹配的Driver物件,呼叫其方法獲取連線
Connection conn = DriverManager.getConnection (
"jdbc:oracle:thin:@192.168.0.26:1521:tarena",
"openlab","open123");
需要注意的是:Connection只是介面,真正的實現是由資料庫廠商提供的驅動包完成的。
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介面接收。
常用處理方式:遍歷 / 判斷是否有結果(登入)。
String sql = "select * from emp";
ResultSetrs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getInt("empno")+",“
+rs.getString("ename") );
}
查詢的結果存放在ResultSet物件的一系列行中,指標的最初位置在行首,使用next()方法用來在行間移動,getXXX()方法用來取得欄位的內容。
處理結果集ResultSet
ResultSet代表DQL查詢結果,是2維結果. 其內部維護了一個讀取資料的遊標,預設情況在,遊標在第一行資料之前, 當呼叫next() 方法時候, 遊標會向下移動,並將返回結果集中是否包含資料, 如果包含資料就返回true. 結果集還提供了很好getXXX方法用於獲取結果集遊標指向當前行資料.
原理:
案例:
/**
* 執行DQL 語句
*/
public class Demo03 {
public static void main(String[] args)
throws Exception{
//註冊驅動
String driver="oracle.jdbc.OracleDriver";;
Class.forName(driver);
//連線資料庫
String url="jdbc:oracle:thin:@192.168.201.227:1521:orcl";
String user="openlab";
String pwd="open123";
Connection conn=DriverManager.getConnection(
url, user, pwd);
//建立Statement
Statement st=conn.createStatement();
//執行SQL(dql)
String sql="select id, name "
+ "from robin_demo ";
ResultSet rs=st.executeQuery(sql);
//處理結果 ...
//rs結果集中包含一個遊標,遊標預設在結果集
//的第一行之前
//rs.next():移動結果集遊標到下一行
//檢查是否有資料, 如果有返回true, 否則false
while(rs.next()){
//getXXX(列名): 返回結果集當前行中
// 指定列名的資料.
int id = rs.getInt("id");
String name=rs.getString("name");
//輸出查詢結果
System.out.println(id+","+name);
}
//關閉連線
conn.close();
}
}
使用Properties 讀取配置檔案
Properties 是Java中專門用於讀取配置檔案的API.
- 其底層就是文字檔案IO
- Properties 本身 實現 Map介面, 內部是散列表
- Properties限定了key和Value都是String 型別.
Properties 常用API方法:
- load(流) 讀取一個配置檔案
- String getProperty(key) 讀取一個屬性值
使用步驟:
- 建立Properties物件
- 利用load方法讀取配置檔案
- 利用getProperty查詢屬性檔案的內容
案例, 讀取配置檔案:
在resource 資料夾中新增配置檔案 db.properties:
# db.properties
jdbc.driver=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.201.227:1521:orcl
jdbc.username=openlab
jdbc.password=open123
使用Properties讀取配置檔案內容:
public class Demo05 {
public static void main(String[] args)
throws IOException{
// Properties 就是為了讀取
// *.properties 檔案而設計的API
// 其底層就是文字檔案IO
// Properties 本身 實現 Map介面
// 內部是散列表, 限定了key和Value都是
// String 型別.
//方法: load(流) 將檔案就讀取為散列表
//String getProperty(key) 查詢value
//使用步驟
//1 建立 Properties 物件
Properties cfg = new Properties();
System.out.println(cfg);
System.out.println(cfg.size());
System.out.println(cfg.isEmpty());
//2. 利用load方法讀取檔案
InputStream in=
Demo05.class.getClassLoader()
.getResourceAsStream("db.properties");
//執行以後,將檔案內容讀取到散列表中了
cfg.load(in);
System.out.println(cfg);
System.out.println(cfg.size());
//3. 查詢檔案內容, 就是讀取檔案內容
String s=
cfg.getProperty("jdbc.driver");
System.out.println(s);
}
}
利用配置檔案可以將程式中的引數儲存到配置檔案中, 修改程式引數只需要修改配置檔案即可.
管理資料庫連線
在軟體中資料庫連線使用非常頻繁, 如果每次都建立連線, 就會造成程式碼的大量冗餘, 常規的做法是建立資料庫連線工具類, 封裝資料庫連線過程, 統一資料庫連線過程, 使用時候就可以簡化程式碼.
實現步驟:
- 建立資料庫連線引數檔案 db.properties
- 建立DbUtils.java 封裝資料庫連線方法
- 利用Properties讀取配置資料夾中的資料庫連線引數
- 建立方法 getConnection 封裝資料庫連線過程
- 使用 getConnection 方法
建立配置檔案 db.properties
# db.properties
jdbc.driver=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.201.227:1521:orcl
jdbc.username=openlab
jdbc.password=open123
建立DbUtils.java
public class DbUtils {
static String driver;
static String url;
static String username;
static String password;
//讀取檔案中的資料庫連線引數
static{
//初始化靜態屬性
//1. 利用Properties 讀取配置檔案
//2. 從配置檔案中查詢 相應引數值
try{
Properties cfg=new Properties();
InputStream in=
DbUtils.class.getClassLoader()
.getResourceAsStream("db.properties");
cfg.load(in);
System.out.println(cfg);
//初始化 連線引數
driver=cfg.getProperty("jdbc.driver");
url=cfg.getProperty("jdbc.url");
username=cfg.getProperty("jdbc.username");
password=cfg.getProperty("jdbc.password");
in.close();
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 封裝建立資料庫連線的過程
* 簡化資料庫連線
*/
public static Connection getConnection(){
try{
Class.forName(driver);
Connection conn=
DriverManager.getConnection(
url, username, password);
return conn;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
//DbUtils.java
/*
* 關閉資料庫的連線方法, 封裝複雜的關閉過程
*/
public static void close(Connection conn){
if(conn!=null){
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
說明:
- driver url username password 是4個數據庫連線引數, 因為只需要一份,則定義為靜態變數.
- 靜態程式碼塊的目的是從配置檔案中讀取4個數據庫連線引數的值.
- getConnection方法封裝了資料庫連線過程
- close方法封裝了資料庫連線關閉的過程
DbUtils 的使用:
public class Demo06 {
public static void main(String[] args) {
Connection conn=null;
try{
conn=DbUtils.getConnection();
Statement st=conn.createStatement();
String sql="select * from robin_demo";
ResultSet rs=st.executeQuery(sql);
while(rs.next()){
int id=rs.getInt("id");
String name=rs.getString("name");
System.out.println(id+","+name);
}
rs.close();//釋放查詢結果
st.close();//釋放語句物件
}catch(Exception e){
e.printStackTrace();
}finally {
DbUtils.close(conn);
}
}
}
顯然: 使用DbUtils可以簡化JDBC程式碼的書寫.
這個程式碼中在finally中關閉資料庫連線, 其好處是可靠關閉連線.