关于PreparedStatement和Statement

版权声明:欢迎转载,请注明作者和出处 https://blog.csdn.net/baichoufei90/article/details/83539484

关于PreparedStatement和Statement

0x01 不同

看了一些网上的博客,主要结论有以下三点:

Statement PreparedStatement
可读性 差,需要拼接字符串 高,可单独设置每个变量
预编译 普通sql无预编译 可配置开启预编译
安全性 差,可能被sql注入到拼接字段 强,sql提前预编译,传入的参数中的字符串,如果有特殊字符会被转义

0x02 开启预编译

很多主流持久层框架(MyBatis,Hibernate)其实都没有真正的用上预编译,预编译是要我们自己在参数列表上面配置的,如果我们不手动开启,JDBC驱动程序5.0.5以后版本 默认预编译都是关闭的。

所以我们要在参数列表中配置,例如:

jdbc:mysql://localhost:3306/mybatis?&useServerPrepStmts=true&cachePrepStmts=true
  • useServerPrepStmts
    表示mysql驱动会先把SQL语句发送给服务器进行预编译,然后在执行executeQuery()时只是把参数发送给服务器
  • cachePrepStmts
    当使用不同的PreparedStatement对象来执行相同的SQL语句时,还是会出现编译两次的现象,这是因为驱动没有缓存编译后的函数key,导致二次编译。如果希望缓存编译后函数的key,那么就要设置cachePrepStmts参数为true

0x03 PreparedStatement

Connector/J有PreparedStatementd的两种实现即客户端侧和服务端的预编译statements:

  • 客户端侧的PreparedStatement是默认选项。因为早期MySQL版本不支持预编译或实现有问题。
  • 服务端侧的PreparedStatement和二进制编码的result set一般是在服务端支持时启用,启用命令是useServerPrepStmts=true

当使用服务端侧的PreparedStatement且参数是用setBinaryStream(), setAsciiStream(), setUnicodeStream(), setCharacterStream(), setNCharacterStream(), setBlob(), setClob(), or setNCLob()设置时一定要特别注意。
重新执行statement,且参数由大参数调整为小参数是,使用clearParameters()方法来重设所有参数。原因如下:

  • 在服务器端预处理语句和客户端仿真期间,只有在调用PreparedStatement.execute()方法时才会交换大数据。

  • 一旦这个过程完成,被用来读取客户端侧数据的流被关闭(根据JDBC规范),而且不能再次读取。

  • 如果一个参数从大转为小,driver就必须重设服务端侧的PreparedStatement状态来允许正在被修改的参数替代之前的大值。这样会移除所有已经被发送到服务端的大型数据,因此需要使用前面讲到的setBinaryStream(), setAsciiStream(), setUnicodeStream(), setCharacterStream(), setNCharacterStream(), setBlob(), setClob(), or setNCLob()方法来重发数据。

0x04 Statement

当使用3.2.1以前版本的JDBC driver连接5.0.3以前版本的myslq 服务时,setFetchSize()方法不生效,

0xFF 参考文档

MySQL Connector/J 5.1 Developer Guide
JDBC中的——PreparedStatement 预编译原理
PreparedStatement的原理
JDBC:深入理解PreparedStatement和Statement
你可能需要重新理解JDBC PreparedStatement
以mysql为例介绍PreparedStatement防止sql注入原理

猜你喜欢

转载自blog.csdn.net/baichoufei90/article/details/83539484