今天同事遇到一个问题,简言之,就是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. Spring详解(七)------事务管理

    PS:本篇博客源码下载链接:http://pan.baidu.com/s/1mi3NhX2 密码:3io2 1.事务介绍 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指 ...

  2. CSS中新属性calc()

    CSS3的calc()使用 原文: http://www.w3cplus.com/css3/how-to-use-css3-calc-function.html © w3cplus.com calc( ...

  3. PHP连接SQL Server数据库

    服务环境:apache2.2 + PHP5.2 + Sql Server 2008 R2 一.所需库和工具1.SQLSRV20.EXE (php5.2版本对应的的Sql Server扩展库)注释:ph ...

  4. NSString与NSMutableString的浅拷贝与深拷贝

    浅拷贝:指针拷贝,指针与原指针地址相同,没有创建新的对象. 深拷贝:内容拷贝,创建了新的对象,指针地址与原对象的指针地址不同. NSString测试代码如下 打印结果如下(后面打印出的两个NSCFCo ...

  5. Window window = Window.GetWindow(控件)

    Window window = Window.GetWindow(控件)

  6. JAVA编程入门

    java最早是由Sun公司基于C++开发而成的新一代编程语言也是现行下的主流行编程语言,其原始的主要用于嵌入式开发.java的第一个版本为JDK1.0,到2017年已经升级到JAK1.9版本.java ...

  7. redis3.2新功能--GEO地理位置命令介绍

    概述 redis3.2发布rc版本已经有一段时间了,估计RedisConf 2016左右,3.2版本就能release了.3.2版本中增加的最大功能就是对GEO(地理位置)的支持.说起redis的GE ...

  8. 80806汇编(5)——[BX]和Loop指令

    80806汇编(5)--[BX]和Loop指令 已经好久没写点东西了,国庆节就一直想弄个个人网站,这段时间一直在弄那个,虽然有现成的框架(Hexo),但是总想弄出自己的效果来,但是最后还是有些差强人意 ...

  9. django中使用sha1,md5加密

    # salt 盐 使用sha1加密算法,返回str加密后的字符串 # 提高字符串的复杂的 from hashlib import sha1 def get_hash(str, salt=None): ...

  10. Java基础-运算符(03)

    概念: 运算符:就是对于常量和变量进行操作的符号. 表达式:用运算符连接起来的符合java语法的式子,不同的运算符连接的表达式是不同类型的表达式. 运算符分类: 算数运算符(+  -  *  /  % ...