简述statement 和preparestatment的区别以
前言
statement 和 PreparedStatement 均为接口,可以用他们来执行sql,但是他们还是有细微的差别。
1、执行sql的样式不同
Statement
Statement执行的是静态的sql对象
PreparedStatement
PreparedStatement既可以执行静态的sql对象,可以往里面出入参数。(这块注意: 参数类型不能错 比如int值就传入int) 样例如下,不多解释
Connection connection = DriverManager.getConnection(CONNECTION_URL,"hadoop","");
statement = connection.prepareStatement("select * from ceshi.test limit ?");
statement.setInt(1,10);
resultSet = statement.executeQuery();
2、PreparedStatement预编译的功能
PreparedStatement执行sql是现在预编译,然后执行executeQuery(),如上面代码所示
但是Statement这里执行的sql确实先拿到Statement ,然后去执行具体的sql语句。比如
Connection connection = DriverManager.getConnection(CONNECTION_URL,"hadoop","");
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from ceshi.test limit 10");
所以这块PreparedStatement可以防止Statement出现的预编译的问题。
3、注意 (重复使用preparestatment和statement的场景)
说到上面这些点,感觉还是PreparedStatement好用,那么是不是任何场景都使用PreparedStatement 就可以了呢?
如今有这么一个需求,我们来执行一个sql来得到一个resultSet。获取数据后,我们在执行另外一个sql获取另外一个resultSet,我们应该怎么做?
statement = connection.prepareStatement("xxx");
resultSet = statement.executeQuery()
statement.executeQuery("xxx")
如果使用这个的话,这样写可以么? 打开PreparedStatement关于executeQuery 的源码,我们看到如下
<strong>Note:</strong>This method cannot be called on a
<code>PreparedStatement</code> or <code>CallableStatement</code>.
说明这个方法不能被executeQuery调用,不然容易抛出异常(但是说实话,我自己测试了也能用,但是确实也是隐患。)
这个时候我们就可以使用Statement来进行操作了,比如
statement = connection.createStatement();
resultSet = statement.executeQuery("select * from ceshi.test limit 10");
while(resultSet.next()) {
System.out.println(resultSet.getString(1));
}
resultSet1 = statement.executeQuery("select * from ceshi.test limit 10");
疑问
这里其实当时有个疑问,就是statement能同时执行多个resultSet么,会不会引起重复
我在statement源码说明的最上面找到了答案,说明如下
By default, only one <code>ResultSet</code> object per <code>Statement</code>
object can be open at the same time. Therefore, if the reading of one
<code>ResultSet</code> object is interleaved
with the reading of another, each must have been generated by
different <code>Statement</code> objects. All execution methods in the
<code>Statement</code> interface implicitly close a current
<code>ResultSet</code> object of the statement if an open one exists.
大意就是,如果同时读取两个resultSet做交互,使用一个Statement是不行的。但是如果是顺序执行的话,是可以的,因为比如当前的resultSet打开的时候,会隐式关闭之前的resultSet