JDBC中的Statement和PreparedStatement的区别

来源:互联网 发布:越前南次郎的实力数据 编辑:程序博客网 时间:2024/05/28 16:00

1:Statement

每次都会执行SQL语句,相关数据库都要执行SQL语句的编译。Statement为一条Sql语句生成执行计划,如果要执行两条sql语句select colume from table where colume=1;select colume from table where colume=2;会生成两个执行计划一千个查询就生成一千个执行计划!

2: PreparedStatement

   用于处理动态SQL语句,在执行前会有一个预编译过程,这个过程是有时间开销的,虽然相对数据库的操作,该时间开销可以忽略不计,  但是PreparedStatement的预编译结果会被缓存,下次执行相同的预编译语句时,就不需要编译,只要将参数直接传入编译过的语句执行代码  中就会得到执行,所以,对于批量处理可以大大提高效率。   (1) PreparedStatement接口继承Statement,PreparedStatement  实例包含已编译的 SQL 语句,         所以其执行速度要快于 Statement 对象。   (2)作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。        三种方法**execute**、 **executeQuery** 和 **executeUpdate** 已被更改以使之不再需要参数

3:应该尽可能以PreparedStatement代替Statement,其原因如下:
(1)代码的可读性和可维护性。从代码比较中就应该能看出来:

stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");//stmt是Statement对象实例perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");perstmt.setString(1,var1);perstmt.setString(2,var2);perstmt.setString(3,var3);perstmt.setString(4,var4);perstmt.executeUpdate(); //prestmt是 PreparedStatement 对象实例

(2)PreparedStatement尽最大可能提高性能。

(3)极大的提高了安全性。
恶意SQL语法

String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";

如果我们把[’ or ‘1’ = ‘1]作为varpasswd传入进来.用户名随意,看看会成为什么?

select * from tb_name = '随意' and passwd = '' or '1' = '1';

因为’1’=’1’肯定成立,所以可以任何通过验证。这算比较委婉的,更有甚者把[‘;drop table tb_name;]作为varpasswd传入进来… 关于数据安全方面的内容这里就不做展开讨论了,总之使用PreparedStatement让执行的SQL更安全。
更有甚者:
把[‘;drop table tb_name;]作为varpasswd传入进来,则:
select * from tb_name = ‘随意’ and passwd = ”;drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑.

罗列出PreparedStatement对象在初级开发中几个常用的方法:

1). PreparedStatement.execute()方法:

该语句可以是任何种类的 SQL 语句
execute 方法返回一个 boolean 值,以指示第一个结果的形式。必须调用 getResultSet 或 getUpdateCount 方法来检索结果,并且必须调用 getMoreResults 移动到任何后面的结果。
返回:
如果第一个结果是 ResultSet 对象,则返回 true;如果第一个结果是更新计数或者没有结果,则返回 false
意思就是如果是查询的话返回true,如果是更新或插入的话就返回false了;

2). PreparedStatement.executeQuery()方法:
返回执行查询语句后得到的ResultSet结果集,注意:该结果集永远不能为null。

3). PreparedStatement.executeUpdate()方法:
返回一个int类型的值,该值代表执行INSERT、DELETE以及UPDATE语句后的更新行数。
如果该值为0,则代表SQL语句没有执行成功。
4).PreparedStatement.addBatch(); executeBatch()方法:
将一组参数添加到此 PreparedStatement 对象的批处理命令中。缓存sql语句,然后批量执行!
将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。

用法举例:

1、增加、修改、删除都用execute(),也可用executeUpdate(),针对于INSERT、UPDATE 或 DELETE 语句

public int addAirEnvironmentPresent(M_AirEnviromentPresentDTO airDTO){      int index = 1;      String sql = "insert into airPresent(airForecastPlace,ForecastTime,TSPvalue,remark) values(?,?,?,?)";      try {       ps = conn.prepareStatement(sql);       ps.setString(index++, airDTO.getAirForecastPlace());       ps.setString(index++, airDTO.getForecastTime());       ps.setString(index++, airDTO.getTSPvalue());       ps.setString(index++, airDTO.getRemark());       ps.execute();         } catch (SQLException e) {       e.printStackTrace();      }      return 1; }

2、查询调用execute(),针对于SELECT语句

    public List<PoiMsgDBPojo> getPoiMsgListAfterTime(String vin, long createTime) throws SQLException {        StringBuffer preparedSQLStringBuffer = new StringBuffer("");        preparedSQLStringBuffer.append("SELECT poi_msg.*,`source`.file_name FROM poi_msg, car, `source`");        preparedSQLStringBuffer.append("WHERE ");        preparedSQLStringBuffer.append("poi_msg.wecar_id=car.wecar_id AND ");        preparedSQLStringBuffer.append("poi_msg.weixin_openid=car.weixin_openid AND ");        preparedSQLStringBuffer.append("poi_msg.`source` = `source`.chn_name AND ");        preparedSQLStringBuffer.append("car.vin=? AND ");        preparedSQLStringBuffer.append("create_time>? ");        preparedSQLStringBuffer.append("ORDER BY create_time DESC limit 20");        List<PoiMsgDBPojo> msgPojoList = new LinkedList<PoiMsgDBPojo>();        Connection connection = null;        PreparedStatement statement = null;        ResultSet resultSet = null;        try {            connection = this.dataSource.getConnection();            statement = connection.prepareStatement(preparedSQLStringBuffer.toString());            statement.setString(1, vin);            statement.setLong(2, createTime);            STD_LOG.info("I'm going to execute [" + statement.toString() + "]");            if (statement.execute()){                resultSet = statement.getResultSet();                while (resultSet.next()) {                    PoiMsgDBPojo msgDBPojo = new PoiMsgDBPojo();                    msgDBPojo.setMsgId(resultSet.getString("id"));                    msgDBPojo.setWecarId(resultSet.getString("wecar_id"));                    msgDBPojo.setWeixinOpenId(resultSet.getString("weixin_openid"));                    msgDBPojo.setCreateTime(resultSet.getLong("create_time"));                    msgDBPojo.setSource(resultSet.getString("file_name"));                    msgDBPojo.setName(resultSet.getString("name"));                    msgDBPojo.setAddress(resultSet.getString("address"));                    msgDBPojo.setPhone(resultSet.getString("phone"));                    msgDBPojo.setCity(resultSet.getString("city"));                    msgDBPojo.setRegion(resultSet.getString("region"));                    msgDBPojo.setLon(resultSet.getDouble("lon"));                    msgDBPojo.setLat(resultSet.getDouble("lat"));                    msgDBPojo.setPrecision(resultSet.getInt("map_precision"));                    msgPojoList.add(msgDBPojo);                }            }        } catch (SQLException e) {            throw e;        } finally {            if (resultSet != null) {                resultSet.close();            }            if (statement != null) {                statement.close();            }            if (connection != null) {                connection.close();            }        }        return msgPojoList;    }

3、查询调用executeQuery(),针对于SELECT语句

public ArrayList getAirEnvironmentPresentAll(){      ArrayList list = new ArrayList();      String sql = "select * from airPresent";      try {       ps = conn.prepareStatement(sql);       rs = ps.executeQuery();       while(rs.next()){        dto = new M_AirEnviromentPresentDTO();        dto.setId(rs.getInt("id"));           dto.setAirForecastPlace(rs.getString("airForecastPlace"));        dto.setForecastTime(rs.getString("forecastTime"));        dto.setTSPvalue(rs.getString("tspvalue"));        dto.setRemark(rs.getString("remark"));        list.add(dto);       }      } catch (SQLException e) {       e.printStackTrace();      }      return list; }

关于PreparedStatement.addBatch()方法

Statement和PreparedStatement的区别就不多废话了,直接说PreparedStatement最重要的addbatch()结构的使用.1.建立链接,(打电话拨号 )       Connection    connection =getConnection();2.不自动 Commit (瓜子不是一个一个吃,全部剥开放桌子上,然后一口舔了)connection.setAutoCommit(false);   3.预编译SQL语句,只编译一回哦,效率高啊.(发明一个剥瓜子的方法,以后不要总想怎么剥瓜子好.就这样剥.)PreparedStatement statement = connection.prepareStatement("INSERT INTO TABLEX VALUES(?, ?)");   4.来一个剥一个,然后放桌子上//记录1statement.setInt(1, 1); statement.setString(2, "Cujo"); statement.addBatch();   //记录2statement.setInt(1, 2); statement.setString(2, "Fred"); statement.addBatch();   //记录3statement.setInt(1, 3); statement.setString(2, "Mark"); statement.addBatch();   //批量执行上面3条语句. 一口吞了,很爽int [] counts = statement.executeBatch();   //Commit it 咽下去,到肚子(DB)里面connection.commit();
stmt.addBatch("update  TABLE1 set 题目="盛夏话足部保健1"   where id="3407""); stmt.addBatch("update  TABLE1 set 题目="夏季预防中暑膳食1" where id="3408""); stmt.addBatch("INSERT INTO  TABLE1  VALUES("11","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("12","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("13","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("14","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("15","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("16","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("17","12","13","","")"); stmt.addBatch("INSERT INTO  TABLE1  VALUES("18","12","13","","")"); int [] updateCounts=stmt.executeBatch(); cn.commit();例如:    public static void execteBatch(Connection conn)throws Exception{        String sql1 = "delete from student where id =3 ";        String sql2 = "delete from student where id =5 ";        String sql3 = "delete from student where id =6 ";        String sql4 = "delete from student where id =7 ";        PreparedStatement pstmt = conn.prepareStatement(sql1);        pstmt.addBatch();        //addBatch(sql2)该方法为继承statement的方法        pstmt.addBatch(sql2);        pstmt.addBatch(sql3);        pstmt.addBatch(sql4);        pstmt.executeBatch();    };
0 0
原创粉丝点击