So sánh Statement và PreparedStatement

1. Ví dụ

Tạo class StatementVsPreparedStatement.java

package com.loop.sql;

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 StatementVsPreparedStatement {

  /**
  * Create by Cuder
  */
  public static void main(String[] args) throws SQLException {
    String userName = "loopUse1";
    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      con = DriverManager.getConnection("jdbc:mysql://localhost:3306/loopTest", "root", "root");
      stmt = con.createStatement();
      rs = stmt.executeQuery("select * from userlogin where userN = '" + userName + "'");
      System.out.println("Statement : ");
      while (rs.next()) {
        System.out.println(rs.getString(1) + " " + rs.getString(2));
      }
    } catch (Exception e) {
      System.out.println(e);
    } finally {
      if (null != rs) {
        rs.close();
      }
      if (null != stmt) {
        stmt.close();
      }
    }
    // =====================================================
    PreparedStatement preSta = null;
    ResultSet rs1 = null;
    try {
      preSta = con.prepareStatement("select * from userlogin where userN = ?");
      preSta.setString(1, userName);
      rs1 = preSta.executeQuery();
      System.out.println("PreparedStatement : ");
      while (rs1.next()) {
        System.out.println(rs1.getString(1) + " " + rs1.getString(2));
      }
    } catch (Exception e) {
      System.out.println(e);
    } finally {
      if (null != rs1) {
        rs1.close();
      }
      if (null != preSta) {
        preSta.close();
      }
      if (null != con) {
        con.close();
      }
    }
  }
}

Kết quả

Statement :
loopUse1 loopPass10
PreparedStatement :
loopUse1 loopPass10

2. Phân tích ví dụ

Ở ví dụ trên thì đều là truy vấn bảng  userlogin với điều kiện  where userN = 'loopUse1'  sử dụng 2 đối tượng khác nhau là Statement và PreparedStatement.

Điểm khác nhau chính là cách truyền giá trị  'loopUse1' nhưng kết quả trả về thì lại giống nhau. Vậy tại sao cần phải chú ý 2 trường hợp này vậy và nó khác nhau thế nào ?

Vậy thực tế khác nhau là gì ?? Đó chính là  SQLInjection. Nếu các bạn chưa nghe thấy nó bảo giờ hày vào google và search xem sao nhé.

Đó là một lỗi về security liên quan đến việc chèn các ký tự đặt biệt của SQL để vượt qua quá trình bảo mật của SQL. Hiện tượng này rất phổ biến đối với các website điện tử khoảng những năm ~ 2005. Và nó xẩy ra do việc truyền giá trị trực tiếp vào câu lệnh SQL.

Ở ví dụ trên thì đó chính là việc truyền trực tiếp giá trị vào khi sử dụng đối tượng Statement. Còn với PreparedStatement thì đã khắc phục được điều đó. Với PreparedStatement mỗi giá trị truyền vào đều phải thông qua việc check, kiểm tra kiều với các hàm setString(), setInt() ..

Như vậy khi nào ta nên dùng Statement và khi nào nên dùng PreparedStatement.

3. Kết luận

Với những kinh nghiệm của mình tôi thường xử lý như sau:

  • Với những trường hợp SQL không cần truyền vào tham số thì sẽ sử dụng đối tượng Statement
  • Với nhưng trường hợp SQL cần truyền vào tham số để filter trong việc select, delete, hay update thì sẽ sử dụng đối tượng PreparedStatement.
Rate this post
Đinh Thế Hiển
 

Mình là người thích viết lách, chia sẻ các trải nghiệm trong cuộc sống. Thích thể thao đặc biệt là thể hình. Hãy kết nối với mình nhé.

Click Here to Leave a Comment Below 0 comments