1. 程式人生 > >JDBC例子2_預處理物件

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步驟完成:

  1. PreparedStatement預處理物件程式碼:
    #獲得預處理物件,需要提供已經使用佔位符處理後的SQL語句
    PreparedStatement psmt = conn.prepareStatement(sql)
  2. 設定實際引數
    void setXxx(int index, Xxx xx) 將指定引數設定指定型別的值
    引數1:index 實際引數序列號,從1開始。
    引數2:xxx 實際引數值,xxx表示具體的型別。
    例如:
    setString(2, “1234”) 把SQL語句中第2個位置的佔位符?替換成實際引數 “1234”
  3. 執行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();
		}
	}

}