1. 程式人生 > >JDBC04----預編譯語句介紹

JDBC04----預編譯語句介紹

 sql的拼接很麻煩,且容易出錯,因此就可以使用預編譯語句。

介面java.sql.Statement有兩個子介面:CallableStatement,PreparedStatement

有兩種型別的sql語句:

1.靜態sql

在執行之前就知道了sql語句的形式。

2.動態sql

一. Statement介面的實現類

1. PreparedStatement

  • PreparedStatement用於預編譯模板SQL語句,在執行時接受SQL輸入引數。eg:PreparedStatement ps=conn.preparedStatement(sql);
  • 在效能和程式碼靈活性上有顯著的提高
  • PreparedStatement物件使用?作為佔位符,即引數標記;eg:  select *from stu where id=?;  insert into stu value(?,?,?);
  • 使用setXXX(index,value)方法將值繫結到引數中,每個引數標記是其順序位置引用,注意index從1開始;eg:ps.setInt(1,stu.getId());
  • PreparedStatement物件執行sql語句:executeQuery()、executeUpdate(),注意,他們沒有引數; eg:ps.executeUpdate();

2. 舉例

public Stu get(int id) {
        ResultSet resultSet=null;
        Connection connection=null;
        PreparedStatement pStatement=null;
        Stu student=new Stu();
        try {
            Class.forName(JDBCUtil.driverName);
            connection=JDBCUtil.getConnection();
            String sql
="select *from stu where id=?"; pStatement=connection.prepareStatement(sql); pStatement.setInt(1, id);//note這裡的id時傳入的,如果傳入引數是student,就可以改成pStatement.setInt(1,student.getId()) resultSet=pStatement.executeQuery(); if(resultSet.next()) { student.setId(resultSet.getInt("id")); student.setName(resultSet.getString("name")); student.setAge(resultSet.getInt("age")); return student; } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { JDBCUtil.close(connection, pStatement, resultSet); } return null; }

3. 如果沒有使用預編譯語句

如果沒有使用預編譯語句的話,假設已經有一個靜態的sql語句了,每一次查詢的age不同,都會往預編池中寫入一次資料。

4. 如果使用預編譯語句

引數統一用?表示,這樣預編譯池中就不會多次寫入資料了。---------(當很多人操作資料庫時,這回很麻煩的)

note: mysql不支援預編譯池,oracle支援預編譯池。

 

6. 使用預編譯可以防止SQL注入。

(1)什麼是SQL注入

就是通過把SQL命令插入到WEB表單提交或輸入域名或頁面請求的查詢字串,最終達到欺騙伺服器執行惡意的SQL語句。(說人話:就是一些錯誤的sql語句,導致了錯誤的sql語義被執行了)

(2)SQL注入舉例

上面是一個使用者登陸的程式碼,當用戶名如上定義時,雖然表中沒有這個使用者,但是最終的結果會發現列印了登陸成功。打印出這一條sql語句:

因此,看到拼接結果可以知道前面那個條件已經滿足了,就不會管or後面的語句了:即name=‘’已經成立了。

如果使用預編譯,因為它執行的時候會把單引號轉義。----也就是防止SQL注入的根源

 如果使用預編譯:

 

 

(3)為什麼PrepareStaet就能防止注入

是因為它把單引號轉義了,變成了\,這樣一來,就無法截斷SQL語句,進而無法拼接SQL語句,基本上沒有辦法注入了。

二. JDBC呼叫輸出引數儲存過程----CallableStatement

1. 建立一個儲存過程

測試下:

2. 使用Java程式來實現呼叫

public void call(){
        Connection connection=JDBCUtil.getConnection();
        CallableStatement cStatement;
        try {
            cStatement = connection.prepareCall("{call getName(?,?)}");
            cStatement.setInt(1, 2);
            cStatement.registerOutParameter(2, Types.VARCHAR);
            cStatement.execute();
            String name=cStatement.getString(2);
            System.out.println(name);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

 

 

 

 

 

 

 

 參考文獻

https://ke.qq.com/course/339214