Java14---JDBC封裝優化,ORM思想
阿新 • • 發佈:2019-01-02
導讀
1.PreparedStatement
2.封裝優化
3.ORM思想
PreparedStatement
–是Statement的子介面
特點:可以設定引數,把帶引數的SQL語句先傳過去,再設定對應引數的值傳過去執行
較Statement來看,PreparedStatement的變化主要在第三,第四步驟 第三步,建立PreparedStatement,傳入帶引數的SQL語句 對於變化的數值,可以引數化,用?做佔位符佔位 String sql = "INSERT INTO t_user (id,username,password,sex," + "id_number,tel,addr) " + "VALUES(t_user_id_seq.NEXTVAL,?,?,?,?,?,?)"; PreoareStatement pstmt=conn.prepareStatement(sql); 第四步,執行SQL語句 1)先設定佔位符的值,發過去值執行SQL語句 每一個問號對應一個索引,從1開始,語句按照從左到右的順序 pstmt.setXXX(索引,對應的值); 2)執行,注意不要再次傳入SQL語句了 int rows = pstmt.executeUpdate();
PreparedStatement vs Statement
直觀看:
利用PreparedStatement不需要拼接,不需要關心單引號的問題
先傳帶引數的SQL語句
在傳引數執行
利用Statement利用拼接,注意文字型要加單引號拼接
把完整的拼接後的語句傳過去執行
效率看: 如果新增1個學生,Statement相對快一點(後者只傳一次) 如果新增100個學生, 對於Statement,迴圈第四步,傳送100次語句過去,都不相同 對於一個語法,傳送過去需要先編譯處理,再執行,編譯100次 對於Preparedstatement,迴圈第四步,傳送100次引數值過去,語句是一樣的 對於帶引數的語句,先預編譯,只要預編譯1次,執行100次,相對效率高一點
從安全形度來看: 需求:登入時,通過使用者名稱和密碼查詢一個使用者 Statement: "SELECT id,username,password,sex FROM t_user WHERE username="+username+" and password='"+password+"'"; PreparedStatement: "SELECT id,username,password,sex FROM t_user WHERE username=? and password=?"; 假如:使用者名稱:aa 密碼:111 結果一致 假如:使用者名稱:aa 密碼:"111' OR '1'='1" Statement中槍,可以查到所有的使用者資訊 PreparedSatement直接報錯,不允許設定 PreparedStatement更安全 PreparedStatement可以替代Statement,我們推薦使用PreparedSatement
封裝優化
1.封裝第一,二步
自創類ConnectionFactory實現
package com.hala.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* Connection工廠類
* 利用這個類獲取連線的資料庫物件
* @author air
*
*/
public class ConnectionFactory {
private static final String DRIVER="oracle.jdbc.driver.OracleDriver";
public static Connection getConnection(){
//這裡把宣告放在try{}裡邊的話成為區域性變數,會報錯
Connection conn=null;
try {
Class.forName(DRIVER);
conn=DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:XE",
"easybuy",
"easybuy");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
}
替換
Connection conn=ConnectionFactory.getConnection();
注意:這裡有兩種優化思想
(1)將常量抽出為private static final 屬性,便於使用改動
(2)將這些常量存在一個配置檔案中,在ConnectionFactory所在的包下建立一個properties檔案
properties:屬性檔案(不能帶引號,否則引號也作為有效的一部分)
鍵值對
key=value
key=value
key=value
Java中:Properties類,集合類,儲存鍵值對
這個類物件可以從properties檔案中載入資料,把所有的鍵值對
載入到記憶體物件中
jdbcinfo.properties
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:XE
username=easybuy
userpassword=easybuy
怎樣獲取檔案中的鍵值對來使用呢?
->更改後的 ConnectionFactory.java
package com.hala.jdbc;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
/**
* Connection工廠類
* 利用這個類獲取連線的資料庫物件
* @author air
*
*/
public class ConnectionFactory {
//用來儲存從檔案中獲得的值
private static String DRIVER;
private static String URL;
private static String USERNAME;
private static String USERPASSWORD;
//利用靜態程式碼塊實現,在類載入時執行,只會執行一次
static{
//1.建立一個Properties物件
Properties prop=new Properties();
try {
//2.載入properties檔案的資料,這種寫法只能對同包下的檔案獲取一個位元組流
//載入後prop裡邊就有了檔案裡邊的鍵值對
prop.load(ConnectionFactory.class.
getResourceAsStream("jdbcinfo.properties"));
//3.通過鍵獲取對應的值,注意大小寫
DRIVER=prop.getProperty("driver");
URL=prop.getProperty("url");
USERNAME=prop.getProperty("username");
USERPASSWORD=prop.getProperty("userpassword");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection(){
//這裡把宣告放在try{}裡邊的話成為區域性變數,會報錯
Connection conn=null;
try {
Class.forName(DRIVER);
conn=DriverManager.getConnection(URL,USERNAME,USERPASSWORD);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
}
2.釋放資源:自創一個類實現
package com.hala.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 釋放資源
* @author air
*
*/
public class DBUtils {
//這裡PreparedStatement是Statement的子介面,所以這裡用Statement即可
public static void close(ResultSet rs,Statement stmt,Connection conn){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
替換
DBUtils.close(rs,stmt,conn);
ORM思想
Object/Relational Mapping
java物件<---->資料庫對映
物件模型 關係模型
實體類(pojo) 表
屬性 列(欄位)
OID 主鍵
物件 記錄
實體類之間的關聯關係 外來鍵
一對一
對映到Java中:
Person Passport
id id
name ...
Passport Person
Person中含有Passport屬性,Passport屬性也含有Person屬性
一對多
Order (訂單) OrderDetail(訂單明細)
List<OrderDetail> Order
Order中含有List<OrderDetail> 屬性,OrderDetail含有Order 屬性
多對多
Teacher Student
List<Student> List<Teacher>
ORM思想其實本質就是將兩個類相互關聯起來
例項:
定義一個方法,
查詢一個訂單,及其對應的明細並返回
要求,返回訂單物件,裡面包含對應的明細集合物件
分步操作:
1.定義一個OrderJDBC類,
定義 Order getOrder(long id){}
2.定義一個OrderDetailJDBC類,
定義 List<OrderDetail> getDetails(long orderId){}
3.定義一個方法,
查詢一個訂單,及其對應的明細並返回
要求,返回訂單物件,裡面包含對應的明細集合物件