今天同事遇到一个问题,简言之,就是PreparedStatement的预编译究竟是怎么发挥作用的...

嘿嘿,说来惭愧,我以前就只知道PreparedStatement比Statement要好,要防SQL注入,就要用PS。

But,它的预编译作用,我却没关注过。现在经过一番研究,我不敢说我已经“了解”了,但是总归是思路清晰了一些,

我把我理解的整理出来希望对大家也有所帮助,有不对的地方请大家指正。

  • 预编译

首先要说的就是“预编译”。我们知道数据库在执行SQL语句的时候,首先要解析这个SQL语句,有一个“执行计划”的概念(差不多就是指寻找执行这个sql语句的一个最优路径)。对于经常执行的sql,数据库会把执行计划给缓存起来,对应的key就是该条sql。那么当再次执行同样的sql的时候,数据库就不再解析了,直接根据key返回相应的执行计划。这就节省了很多时间。

  • PreparedStatement(后面简称PS)

当我们说到PS的时候,可能我们会关心几个问题:

  1. 预编译发生在什么时候
  2. PS何时被缓存起来的

回答第一个问题:

“在创建PreparedStatement 对象时就指定了SQL语句,该语句立即发送给DBMS进行编译”。

回答第二个问题:

是当我们执行PS的close()方法时~~~~

  •  TEST

我针对PS cache,做了一个测验,想法是针对同一个SQL,如果我每次取到的PS都是同一个,说明确实是拿的缓存的....

代码如下:

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException; import oracle.jdbc.OracleConnection; public class Test
{
static Connection con = null;
public static void main(String args[]) throws ClassNotFoundException, SQLException
{
con = ((oracle.jdbc.OracleConnection)getConnection());
PreparedStatement ps0 = getPS(con);
ps0.close();
PreparedStatement ps1 = getPS(con);
ps1.close();
System.out.println(ps0==ps1);//如果是true,说明cache发生了作用 con.close();
con = null;
con = ((oracle.jdbc.OracleConnection)getConnection());
PreparedStatement ps2 = getPS(con);
ps2.close();
con.close();
System.out.println(ps1==ps2);//如果是false,说明connection关闭后,会重新缓存 } //获取PS实例
public static PreparedStatement getPS(Connection con)throws ClassNotFoundException, SQLException{ String sql = "select * from cms_turbine t where t.mapping like ?";
PreparedStatement ps1 = con.prepareStatement(sql);
ps1.setString(1, "hello");
return ps1;
} //建立连接
public static Connection getConnection(){
if(con == null){
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1523:XXX",xx,xx); //下面两句是为了开启cache
((oracle.jdbc.OracleConnection)con).setImplicitCachingEnabled(true);
((oracle.jdbc.OracleConnection)con).setStatementCacheSize(10);
}catch(Exception e){
e.printStackTrace();
}
}
return con;
}
}

执行结果是: true

false

说明同一个connection中两次取到的PS是同一个实例,不同connection不共用PS。

Note:

如果想要reuse PS,那再用完一个之后一定要close,意味着释放资源。在上面的代码中,如果main方法改写如下:

  public static void main(String args[]) throws ClassNotFoundException, SQLException
{
con = ((oracle.jdbc.OracleConnection)getConnection());
PreparedStatement ps0 = getPS(con);
ps0.close();
PreparedStatement ps1 = getPS(con);
// ps1.close(); ps1不close,后面ps2拿到的还是ps0吗?
System.out.println(ps0==ps1); PreparedStatement ps2 = getPS(con);
ps2.close();
con.close();
System.out.println(ps0==ps2);
}

执行结果是:true (因为ps0 close了)

false(因为ps1没有close,所以ps2并没有能拿到缓存中的PS)

参考:

http://www.linuxidc.com/Linux/2011-07/38776.htm

http://docs.oracle.com/cd/E11882_01/java.112/e10589/stmtcach.htm#JJDBC28649

[J2EE] 有关 PreparedStatement的更多相关文章

  1. java.sql.preparedstatement和java.sql.statement的区别

    本文转自CSDN,然后整理了一遍.原文出处:CSDN JDBC(java database connectivity,java数据库连接)的api中的主要的四个类之一的java.sql.stateme ...

  2. PreparedStatement是如何大幅度提高性能的

    本文讲述了如何正确的使用prepared statements.为什么它可以让你的应用程序运行的更快,和同样的让数据库操作变的更快.  为什么Prepared Statements非常重要?如何正确的 ...

  3. J2EE学习路线

    第一部分:  JAVA语言基础知识.包括异常.IO流.多线程.集合类.数据库.(切记基础知识一定要时时刻刻巩固,注意,如果你是想以最快速度学习J2EE,关于Java中的Swing知识点,就只做了解)  ...

  4. j2EE经典面试题

    1. hibernate中离线查询去除重复项怎么加条件? dc.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 2. http协议及端口,sm ...

  5. 回头探索JDBC及PreparedStatement防SQL注入原理

    概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...

  6. BEA WebLogic平台下J2EE调优攻略--转载

    BEA WebLogic平台下J2EE调优攻略   2008-06-25 作者:周海根 出处:网络   前 言 随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供 ...

  7. J2EE 学习路线

    分享一个比较好的学习网站    http://edu.51cto.com/roadmap/view/id-86.html ================================J2EE=== ...

  8. JDBC及PreparedStatement防SQL注入

    概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...

  9. [J2EE规范]JDBC简单例子 标签: 数据库j2eejdbcjava 2017-06-29 10:55 353人阅读 评论(12)

    JDBC是什么? JDBC是java数据库连接(Java Database Connectivity),它是用于java编程语言和数据库之间的数据库无关连接的标准Java API,就是说,JDBC是用 ...

随机推荐

  1. Python数据分析(二): Numpy技巧 (2/4)

    numpy.pandas.matplotlib(+seaborn)是python数据分析/机器学习的基本工具. numpy的内容特别丰富,我这里只能介绍一下比较常见的方法和属性.   昨天晚上发了第一 ...

  2. Number Complement

    Given a positive integer, output its complement number. The complement strategy is to flip the bits ...

  3. Theano学习-梯度计算

    1. 计算梯度 创建一个函数 \(y\) ,并且计算关于其参数 \(x\) 的微分. 为了实现这一功能,将使用函数 \(T.grad\) . 例如:计算 \(x^2\) 关于参数 \(x\) 的梯度. ...

  4. libsvn_subr-1.so.0: undefined symbol: apr_atomic_xchgptr 故障解决

    源码编译安装完成之后,查看svn的安装版本会报以下错误 svn: symbol lookup error: /usr/local/subversion/lib/libsvn_subr-.so.: un ...

  5. java web 学习笔记 编码问题总结

       java web 学习笔记 编码问题总结 1.非form表单中提交的中文参数---------------------------传递给Servlet服务器时,默认以iso-8859-1解码 ...

  6. wpf 画刷的分类

    System.Windows.Media.Brush最上一层画刷 System.Windows.Media.GradientBrush  线性画刷 ,下层主要有两种画刷 System.Windows. ...

  7. zabbix基本操作

    zabbix基本操作 ---- 2016年终总结 二 包括的内容: 添加主机 查看监控数据 添加监控项 创建触发器 创建模版 添加报警 添加媒介 添加主机 进入页面 点击Configuration(大 ...

  8. JAVAEE企业级应用开发浅谈第二辑:MVC和三层架构

    上海尚学堂警句:一份信心,一份努力,一份成功:十分信心,十分努力,十分成功. Step1.情景概要 Hello,小伙伴们,昨天跟大家分享了JAVA EE 企业级应用开发中大家耳熟能详的概念-三层架构, ...

  9. 上传代码 CodePlex

    博客园作为博客备份,博客会更新一份在博客园 CodePlex是微软开源项目网站,有很多人都在上面传代码,我们也可以上传自己的代码 注册 我们可以用微软账号注册,填写用户名.密码,很快就好. 新建项目 ...

  10. windows server 2003安装 SQL server 2008r2 版本的步骤

    大家好,这里介绍的是在系统 windows server 2003安装 SQL server 20008r2版本,如有雷同,敬请谅解,如果错误,欢迎大家多提意见 1.下载好安装包解压以后,就会出现如下 ...