[J2EE] 有关 PreparedStatement
今天同事遇到一个问题,简言之,就是PreparedStatement的预编译究竟是怎么发挥作用的...
嘿嘿,说来惭愧,我以前就只知道PreparedStatement比Statement要好,要防SQL注入,就要用PS。
But,它的预编译作用,我却没关注过。现在经过一番研究,我不敢说我已经“了解”了,但是总归是思路清晰了一些,
我把我理解的整理出来希望对大家也有所帮助,有不对的地方请大家指正。
- 预编译
首先要说的就是“预编译”。我们知道数据库在执行SQL语句的时候,首先要解析这个SQL语句,有一个“执行计划”的概念(差不多就是指寻找执行这个sql语句的一个最优路径)。对于经常执行的sql,数据库会把执行计划给缓存起来,对应的key就是该条sql。那么当再次执行同样的sql的时候,数据库就不再解析了,直接根据key返回相应的执行计划。这就节省了很多时间。
- PreparedStatement(后面简称PS)
当我们说到PS的时候,可能我们会关心几个问题:
- 预编译发生在什么时候
- 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的更多相关文章
- java.sql.preparedstatement和java.sql.statement的区别
本文转自CSDN,然后整理了一遍.原文出处:CSDN JDBC(java database connectivity,java数据库连接)的api中的主要的四个类之一的java.sql.stateme ...
- PreparedStatement是如何大幅度提高性能的
本文讲述了如何正确的使用prepared statements.为什么它可以让你的应用程序运行的更快,和同样的让数据库操作变的更快. 为什么Prepared Statements非常重要?如何正确的 ...
- J2EE学习路线
第一部分: JAVA语言基础知识.包括异常.IO流.多线程.集合类.数据库.(切记基础知识一定要时时刻刻巩固,注意,如果你是想以最快速度学习J2EE,关于Java中的Swing知识点,就只做了解) ...
- j2EE经典面试题
1. hibernate中离线查询去除重复项怎么加条件? dc.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 2. http协议及端口,sm ...
- 回头探索JDBC及PreparedStatement防SQL注入原理
概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...
- BEA WebLogic平台下J2EE调优攻略--转载
BEA WebLogic平台下J2EE调优攻略 2008-06-25 作者:周海根 出处:网络 前 言 随着近来J2EE软件广泛地应用于各行各业,系统调优也越来越引起软件开发者和应用服务器提供 ...
- J2EE 学习路线
分享一个比较好的学习网站 http://edu.51cto.com/roadmap/view/id-86.html ================================J2EE=== ...
- JDBC及PreparedStatement防SQL注入
概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...
- [J2EE规范]JDBC简单例子 标签: 数据库j2eejdbcjava 2017-06-29 10:55 353人阅读 评论(12)
JDBC是什么? JDBC是java数据库连接(Java Database Connectivity),它是用于java编程语言和数据库之间的数据库无关连接的标准Java API,就是说,JDBC是用 ...
随机推荐
- 【运维】CPU负载
最近对我的本本(4核8线程)用top命令看系统状况出现了CPU利用率超过200%的情况,非常诧异,查了下相关资料,把这个问题弄清楚了.首先来分析下CPU Load load average: 0.09 ...
- 当前页面的url未注册 微信支付
原因1:公众号支付授权目录或测试授权目录设置不正确. 原因2:微信SDK"WxPay.JsApiPay.php"文件中GetOpenid方法中$baseUrl的拼接的结果与支付授权 ...
- Java中Math.round()函数
Math.round(11.5) = 12; Math.round(-11.5) = -11; Math.round()函数是求某个数的整数部分,且四舍五入.
- 强大的grep,sed和awk--用案例来讲解
准备工作: 先简单了解grep,sed和awk功能 1) grep 显示匹配特定模式的内容 grep -v 'boy' test.txt 过滤掉test.txt文件的boy,显示其余内容 grep ' ...
- linux RPM软件包管理
linux RPM软件包管理 目录 1.软件包的介绍 2.rpm包管理 3.rpm包管理前端工具 1.软件包的介绍 在我们在对软件包管理前,先对软件包有个很好的了解,这样更方便我们来对其进行管理. 软 ...
- 如何用IDEA一步一步开发WebService服务器端
工具:IntelliJ IDEA 15.0.4 IDEA这款IDE还是非常强大的,对WebService也有很好的支持.下面我们来一步一步的实现WebService服务器端: 第一步,新建一个工程:F ...
- uva12716 GCD XOR
个人博客:http://acbingo.cn/2015/06/04/uva12716/ 被紫薯上*和素数筛法类似*这句话给误解了= =,一直以为存在某种关系,在枚举c或者a时,可以根据当前的答案,筛掉 ...
- shell编程/字库裁剪(3)——验证
版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/7712496.html 作者:窗户 Q ...
- JQuery-基础学习1
1)JQuery语法 jquery语法是为HTML元素的选取编制,可以对元素执行某些操作. 基础语法是:$(selector).action() 美元符号定义JQuery 选择符(selector)& ...
- LINUX 笔记-watch命令
命令格式:watch[参数][命令] 可以将命令的输出结果输出到标准输出设备,多用于周期性执行命令/定时执行命令 命令参数: -n或--interval watch缺省每2秒运行一下程序,可以用-n ...