一、PreparedStatement 接口的使用
首先占位符我們可以使用 Statement 接口來操作數據, 但是這個接口存在兩個問題:
1、使用 Statement 接口對象發送的 sql 語句需要在數據庫中進行一次編譯之后成為指令才能執行,
並且每條 sql 語句都需要編譯一次, 這樣效率是很慢的。
2、使用 Statement 接口操作的 sql 可以使用字符串拼接的方式實現, 這樣的方式可能存在 sql 注入
的安全風險問題,並且拼接字符串比較麻煩。
解決以上兩個問題我們可以使用 PreparedStatement 接口來避免。 使用 PreparedStatement 接口
操作的 sql 語句會先預編譯成指令再發送給數據庫,數據庫
就執行指令即可,這樣提高 一定的速度,而且使用 PreparedStatement 接口可以避開 sql 需要要使用
字符串拼接的方式,從而使用占位符(?)來代替。這樣就解決了 sql 注入的安全風險。
使用占位符示例代碼如下:
package sxt.scc; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import sxt.scc.util.ConnectionUtil; public class SqlInject { // 取得連接 private static Connection conn= ConnectionUtil.getConnection(); public static void main(String[] args) { selectLogin("smith","1234"); } public static boolean selectLogin(String name,String password) { //准備sql語句 String sql= "SELECT * FROM myuser WHERE username=? AND password=?"; System.out.println(sql); try { PreparedStatement pst =conn.prepareStatement(sql); //為占位符設置具體內容 pst.setString(1, name); pst.setString(2, password); //發送sql語句 ResultSet rst = pst.executeQuery(); if (rst.next()) { System.out.println("登錄成功!"); }else { System.out.println("用戶名不正確"); } } catch (SQLException e) { e.printStackTrace(); } return false; } }
使用占位符這樣就解決了 sql 注入的安全風險。
使用占位符插入數據示例如下:
package sxt.scc.vo; import java.io.Serializable; import java.util.Date; public class Emp implements Serializable{ private Integer empno; private String ename; private String job; private Integer mgr; private Date hiredate; private Double sal; private Double comm; private Integer deptno; public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, Double sal, Double comm, Integer deptno) { super(); this.empno = empno; this.ename = ename; this.job = job; this.mgr = mgr; this.hiredate = hiredate; this.sal = sal; this.comm = comm; this.deptno = deptno; } public Emp() { super(); } public Double getComm() { return comm; } public Integer getDeptno() { return deptno; } public Integer getEmpno() { return empno; } public String getEname() { return ename; } public Date getHiredate() { return hiredate; } public String getJob() { return job; } public Integer getMgr() { return mgr; } public Double getSal() { return sal; } public void setComm(Double comm) { this.comm = comm; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public void setEmpno(Integer empno) { this.empno = empno; } public void setEname(String ename) { this.ename = ename; } public void setHiredate(Date hiredate) { this.hiredate = hiredate; } public void setJob(String job) { this.job = job; } public void setMgr(Integer mgr) { this.mgr = mgr; } public void setSal(Double sal) { this.sal = sal; } @Override public String toString() { return "Emp [empno=" + empno + ", ename=" + ename + ", job=" + job + ", mgr=" + mgr + ", hiredate=" + hiredate + ", sal=" + sal + ", comm=" + comm + ", deptno=" + deptno + "]"; } }
public class TesMysql { //取得連接 private static Connection conn = ConnectionUtil.getConnection(); public static void main(String[] args) throws Exception { //調用下面的方法 insertEmp();
}
//問:使用占位符插入數據 public static boolean insertEmp(Emp emp) throws SQLException { //取得Connection連接對象 Connection conn = ConnectionUtil.getConnection(); //定義sql語句 String sql= "INSERT INTO emp(ename, job, sal, hiredate, mgr, comm, deptno)" + "VALUES(?,?,?,?,?,?,?)"; //取得發送sql語句對象 PreparedStatement pst = conn.prepareStatement(sql); //為占位符賦值 pst.setObject(1, emp.getEname()); pst.setObject(2, emp.getJob()); pst.setObject(3, emp.getSal()); pst.setObject(4, new java.sql.Date(emp.getHiredate().getTime())); pst.setObject(5, emp.getMgr()); pst.setObject(6, emp.getComm()); pst.setObject(7, emp.getDeptno()); //執行sql語句 int row = pst.executeUpdate(); //取得自動增長的主鍵值 ConnectionUtil.close(conn); return row > 0; }
以上代碼就是使用占位符和PreparedStatement接口的使用了。