JDBC例子2_預處理物件
3.1 SQL注入問題
SQL注入:使用者輸入的內容作為了SQL語句語法的一部分,改變了原有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來解決對應的問題。
示例演示:
CREATE TABLE user( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(100), PASSWORD VARCHAR(100) ); INSERT INTO user (username,PASSWORD) VALUES ('a','1'),('b','2'); SELECT * FROM user; -- 登入查詢 SELECT * FROM user WHERE username='xxx' AND PASSWORD='xxx' OR 'a'='a'
使用sql語句就可以很簡單通過檢測;
3.2 預處理物件
preparedStatement:預編譯物件,是Statement物件的子類。
特點:
效能高
會把sql語句先編譯
能過濾掉使用者輸入的關鍵字。
PreparedStatement預處理物件,處理的每條sql語句中所有的實際引數,都必須使用佔位符?替換。
String sql = “select * from user where username = ? and password = ?”;
PreparedStatement使用,需要通過以下3步驟完成:
- PreparedStatement預處理物件程式碼:
#獲得預處理物件,需要提供已經使用佔位符處理後的SQL語句
PreparedStatement psmt = conn.prepareStatement(sql) - 設定實際引數
void setXxx(int index, Xxx xx) 將指定引數設定指定型別的值
引數1:index 實際引數序列號,從1開始。
引數2:xxx 實際引數值,xxx表示具體的型別。
例如:
setString(2, “1234”) 把SQL語句中第2個位置的佔位符?替換成實際引數 “1234” - 執行SQL語句:
int executeUpdate(); --執行insert update delete語句.
ResultSet executeQuery(); --執行select語句.
boolean execute(); --執行select返回true 執行其他的語句返回false.
3.2.1 解決前面的sql注入問題
public static void main(String[] args) throws Exception {
String url="jdbc:mysql://localhost:3306/smbms";
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(url,"root","neapadmin");
Scanner sc=new Scanner(System.in);
System.out.println("請輸入賬號:");
String userName=sc.nextLine();
System.out.println("請輸入密碼:");
String password=sc.nextLine();
String sql="select * from user where username=? and password=?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1,userName);
stmt.setString(2,password);
System.out.println(sql);
ResultSet rs = stmt.executeQuery();
if(rs.next()) {
System.out.println("login success");
}else {
System.out.println("login failure");
}
rs.close();
stmt.close();
conn.close();
}
例子:使用預處理物件,完成對某張表的增刪改查。
package cn.njit.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PreStaDemo {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String jdbcurl="jdbc:mysql://localhost:3306/njit?useUnicode=true&characterEncoding=UTF-8";
String user="root";
String password="admin";
try {
Connection conn=DriverManager.getConnection(jdbcurl, user, password);
String sql;
PreparedStatement ppst;
sql="insert into dept(deptno,dname) values(?,?);";
ppst=conn.prepareStatement(sql);
ppst.setString(1, "10010");
ppst.setString(2, "中國聯不通");
ppst.executeUpdate();
System.out.println("插入成功");
sql="select * from dept where deptno=?;";
ppst=conn.prepareStatement(sql);
ppst.setString(1, "10086");
ResultSet rs=ppst.executeQuery();
System.out.println("部門編號\t部門名稱");
while(rs.next()) {
String deptno=rs.getString("deptno");
String dname=rs.getString("dname");
System.out.println(deptno+"\t"+dname);
}
System.out.println("查詢結束");
rs.close();
ppst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
3.3 插入資料,獲取自增長值
步驟:
PreparedStatement pstmt;
ResultSet rs;
String sql_dept = “insert into dept(deptName) values(?)”;
pstmt = con.prepareStatement(sql_dept, Statement.RETURN_GENERATED_KEYS);
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
// 得到返回的自增長欄位
if (rs.next()) {
deptId = rs.getInt(1);
}
只有int型才能設計為自增長;
插入時自動長,不需要插入資料;
package cn.njit.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PreStaDemo {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String jdbcurl="jdbc:mysql://localhost:3306/njit?useUnicode=true&characterEncoding=UTF-8";
String user="root";
String password="admin";
try {
Connection conn=DriverManager.getConnection(jdbcurl, user, password);
String sql;
PreparedStatement ppst;
sql="insert into stu(name,sex) values(?,?);";
ppst=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
ppst.setString(1, "螺紋");
ppst.setString(2, "男");
ppst.executeUpdate();
ResultSet rss=ppst.getGeneratedKeys();
int id=0;
while(rss.next()) {
id=rss.getInt(1);
System.out.println(id);
}
rss.close();
ppst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}