Preparedstatement和Statement的区别

时间:2021-05-19 11:57:11
       PreparedStatement是预编译的, Preparedstatement支持批处理,对于批量处理可以大大提高效率。
       Statement每次执行sql语句,相关数据库都要执行sql语句的编译。对于只执行一次的SQL语句选择Statement是最好的。因为PreparedStatement对象的开销比Statement大,对于一次性操作并不会带来额外的好处。相反,如果SQL语句被多次执行选用PreparedStatement是最好的.PreparedStatement的第一次执行消耗是很高的. 它的性能体现在后面的重复执行.

       PreparedStatement是预编译的,每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个函数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.事实是没有数据库会对普通语句编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次.
       当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.

使用PreparedStatement有几个好处 :
       1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
       2. 安全性好,有效防止Sql注入等问题。
       3.对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;
       4.代码的可读性和可维护性。


       在使用SpringJDBC其中的template的类型为org.springframework.jdbc.core.JdbcTemplate时,使用JdbcTemplate类型提供的update方法:
public void create(Item item) throws IOException {
template.update(
"insert into items (name, price, prc_date) values (?, ?, now())",
item.name, item.price);
}
       但是,直接使用update方法的这一重载并不是最快的。可以使用public int update(String sql, PreparedStatementSetter pss)这一重载来得到更佳的运行速度:
public void create(CartItemRelation item) throws IOException {
template.update(
"insert into item (name, price, prc_date) values (?, ?, now())",
new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, item.name);
ps.setBigDecimal(2, item.price);
}
});
}
       如果使用Java 8的Lambda表达式,上述代码仍然有简化的空间:
public void create(final Item item) throws IOException {
template.update(
"insert into items (name, price, prc_date) values (?, ?, now())",
ps -> {
ps.setString(1, item.name);
ps.setBigDecimal(2, item.price);
});
}