【前言】

   小编在敲drp项目的时候,偶遇了prepareStatement和Statement这两对象,看着就觉得这两个对象关系匪浅,的确prepareStatement继承了Statement,所以prepareStatement在Statement的基础肯定扩展了她的方法,而且很具有优势,下面小编就简单的讲讲我对这两个对象的看法:

【内容】

1. prepareStatement和Statement的区别:



 

安全性

效率

开销

可读性

维护性

prepareStatement

高,预编译

容易

Statement

容易发生sql注入

低,每一次编译

不容易


2.prepareStatement和Statement的基本语法:

//Statement的语法
String updateString = "UPDATE User SET SALES = 75 " + "WHERE User_Name LIKE ′cyl′";
stmt.executeUpdate(updateString);

//prepareStatement的语法
PreparedStatement updateUser = con.prepareStatement("UPDATE User SET SALES = ? WHERE User_Name LIKE ? ");
updateUser.setInt(1, 75);
updateUser .setString(2, "Colombian");
updateUser .executeUpdate();






3.prepareStatement和Statement的使用情况

@一般情况参数固定,需要多次执行删除或者查询语句的时候,使用prepareStatement会比Statement好很多

 prepareStatement: 


/**
    * 删除单个用户
    * @param userId
    */
   public void delUser(String userId){
	   String sqldelString="delete from t_user where user_id=?";
	   Connection connection=null;
	   PreparedStatement psmt=null;
	   try {
		 connection=DbUtil.getConnection();
		 psmt=connection.prepareStatement(sqldelString);
		 psmt.setString(1, userId); //设置参数
		 psmt.executeUpdate();
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DbUtil.close(psmt);
		DbUtil.close(connection);
	}

  }


Statement:

/**
    * 删除单个用户
    * @param userId
    */
   public void delUser(String userId){
	   String sqldelString="delete from t_user where user_id"+userId; //直接将参数放入sql语句中
	   Connection connection=null;
	   java.sql.Statement stmt=null;
	   try {
		 connection=DbUtil.getConnection();
		 stmt=connection.createStatement();
		 stmt.executeUpdate(sqldelString);
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DbUtil.close(stmt);
		DbUtil.close(connection);
	}

  }




单从代码量来看,Statement的确比prepareStatement的少两行,因为有sql参数的设置。但是从可读性和维护性上,prepareStatement的sql的语句类型一旦确定,就不需要过多的修改,参数与sql语句分离,提高维护性。从安全性的角度来说,如果用Statement进行select查询很容易会产生sql注入,把["or '1'='1"]数据传进来,所有的未或注册的用户可以随意访问,很容易泄露。

所以得出的结论是在一般情况下,我们都尽量使用prepareStatement而不是Statement。

-----------------------------------------------------------------------------

@特殊情况在参数的个数不确定的情况下,使用PrepareStatement和Statement没有什么区别。因为执行的sql语句都会被重新的编译,使用stringbuilder也可以防止sql注入,代码如下:

PrepareStatement:


/**
   * 批量删除
   * 采用提交一次完成删除
   * 采用preparedstatement占位符的方式
   * delete from t_user where user_id in(?,?,?);
   * @param userIds
   */
 public void delUser(String[] userIds) {
	  StringBuilder sBuilder=new StringBuilder();
	  for (int i = 0; i < userIds.length; i++) {   //使用stringbuilder加载占位符。
		  sBuilder.append("?");
		  if (i<(userIds.length-1)) {
			sBuilder.append(",");
		}	
	}
	 String sqlString="delete from t_user where user_id in ("+sBuilder.toString()+")";
	 System.out.println(sqlString);
	  Connection connection=null;
	  PreparedStatement stmt=null;
	  try {
	    connection=DbUtil.getConnection();
	    stmt=connection.prepareStatement(sqlString);
	    //射进来的参数-stringbuiler
		for (int i = 0; i < userIds.length; i++) { 
			stmt.setString(i+1, userIds[i]);
		}
		stmt.executeUpdate();
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		DbUtil.close(stmt);
		DbUtil.close(connection);	
	}
	
}


Statement:


//{{  void delUser(String[] userIds)+常银玲
  
   /**
    * 批量删除
    * 采用提交一次完成删除——事务-cyl
    * 采用statement拼串方式
    * delete from t_user where user_id in();
    * @param userIds
    */
  public void delUser(String[] userIds) {
	  StringBuilder sBuilder=new StringBuilder();
	  for (int i = 0; i < userIds.length; i++) {  //使用stringbuilder加载参数
		  sBuilder.append("'")
		  .append(userIds[i])
		  .append("'")
		  .append(",");
	}
	 String sqlString="delete from t_user where user_id in ("+sBuilder.substring(0,sBuilder.length()-1)+")";
	 System.out.println(sqlString);
	  Connection connection=null;
	  java.sql.Statement stmt=null;
	 // ResultSet rSet=null;
	  try {
	    connection=DbUtil.getConnection();
		stmt=connection.createStatement();
		stmt.executeUpdate(sqlString);
	} catch (Exception e) {
		e.printStackTrace();
	}finally{
		//DbUtil.close(rSet);
		DbUtil.close(stmt);
		DbUtil.close(connection);	
	}
	
}
  //}}

【总结】

其实使用prepareStatement已经成为我们的首选,必定它有着比Statement更多的优势,而且prepareStatement更加体现我们面向对象的一种思想,将sql语句与参数分离,参数的类型已经参数值不会对既定的sql语句产生很大的影响,而且最重要的就它可以进行预编译,对我们程序的性能会有很大的改善,而且可以防止sql注入,提高我们程序的安全性。希望这篇博文让你对prepareStatement有了一些了解,如果有什么偏差,希望可以在谅解的同时提出您的想法!