PreparedStatement的使用
1.1 PreparedStatement介紹
-
可以通過呼叫 Connection 物件的 preparedStatement(String sql) 方法獲取 PreparedStatement 物件
-
PreparedStatement 介面是 Statement 的子介面,它表示一條預編譯過的 SQL 陳述句
-
PreparedStatement 物件所代表的 SQL 陳述句中的引數用問號(?)來表示,呼叫 PreparedStatement 物件的 setXxx() 方法來設定這些引數. setXxx() 方法有兩個引數,第一個引數是要設定的 SQL 陳述句中的引數的索引(從 1 開始),第二個是設定的 SQL 陳述句中的引數的值
1.2 PreparedStatement vs Statement
-
代碼的可讀性和可維護性,
-
PreparedStatement 能最大可能提高性能:
- DBServer會對預編譯陳述句提供性能優化,因為預編譯陳述句有可能被重復呼叫,所以陳述句在被DBServer的編譯器編譯后的執行代碼被快取下來,那么下次呼叫時只要是相同的預編譯陳述句就不需要編譯,只要將引數直接傳入編譯過的陳述句執行代碼中就會得到執行,
- 在statement陳述句中,即使是相同操作但因為資料內容不一樣,所以整個陳述句本身不能匹配,沒有快取陳述句的意義.事實是沒有資料庫會對普通陳述句編譯后的執行代碼快取,這樣每執行一次都要對傳入的陳述句編譯一次,
- (語法檢查,語意檢查,翻譯成二進制命令,快取)
-
PreparedStatement 可以防止 SQL 注入
1.3 ORM思想(object relational mapping)
- 一個資料表對應一個java類
- 表中的一條記錄對應java類的一個物件
- 表中的一個欄位對應java類的一個屬性
sql是需要結合列名和表的屬性名來寫,注意起別名,
Java與SQL對應資料型別轉換表
| Java型別 | SQL型別 |
|---|---|
| boolean | BIT |
| byte | TINYINT |
| short | SMALLINT |
| int | INTEGER |
| long | BIGINT |
| String | CHAR,VARCHAR,LONGVARCHAR |
| byte array | BINARY , VAR BINARY |
| java.sql.Date | DATE |
| java.sql.Time | TIME |
| java.sql.Timestamp | TIMESTAMP |
1.4 使用PreparedStatement實作增、刪、改操作
//通用的增、刪、改操作(體現一:增、刪、改 ; 體現二:針對于不同的表)
public void update(String sql,Object ... args){
Connection conn = null;
PreparedStatement ps = null;
try {
//1.獲取資料庫的連接
conn = JDBCUtils.getConnection();
//2.獲取PreparedStatement的實體 (或:預編譯sql陳述句)
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i = 0;i < args.length;i++){
ps.setObject(i + 1, args[i]);
}
//4.執行sql陳述句
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.關閉資源
JDBCUtils.closeResource(conn, ps);
}
}
1.5 使用PreparedStatement實作查詢操作
// 通用的針對于不同表的查詢:回傳一個物件
public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1.獲取資料庫連接
conn = JDBCUtils.getConnection();
// 2.預編譯sql陳述句,得到PreparedStatement物件
ps = conn.prepareStatement(sql);
// 3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 4.執行executeQuery(),得到結果集:ResultSet
rs = ps.executeQuery();
// 5.得到結果集的元資料:ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 6.1通過ResultSetMetaData得到columnCount,columnLabel;通過ResultSet得到列值
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
T t = clazz.newInstance();
for (int i = 0; i < columnCount; i++) {// 遍歷每一個列
// 獲取列值
Object columnVal = rs.getObject(i + 1);
// 獲取列的別名:列的別名,使用類的屬性名充當
String columnLabel = rsmd.getColumnLabel(i + 1);
// 6.2使用反射,給物件的相應屬性賦值
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columnVal);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 7.關閉資源
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
說明:使用PreparedStatement實作的查詢操作可以替換Statement實作的查詢操作,解決Statement拼串和SQL注入問題,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/280211.html
標籤:其他
上一篇:資料庫操作之PreparedStatement的使用
下一篇:SQL總結
