[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是用 ...
随机推荐
- 【转】常用Maven插件
我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...
- 使用SoapUI工具做get请求和post请求接口测试
祝大家节日快乐啦. 之前写过的一篇帖子已经介绍了SoapUI工具的基本使用,所以在此不再重复讲解关于建工程.建测试套件.添加用例等操作,可查看该篇文章详解:http://www.cnblogs.com ...
- Egg + Vue 服务端渲染工程化实现
在实现 egg + vue 服务端渲染工程化实现之前,我们先来看看前面两篇关于Webpack构建和Egg的文章: 在 Webpack工程化解决方案easywebpack 文章中我们提到了基于 Vue ...
- ASP.NET Core 2.0 支付宝当面付之扫码支付
前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等.我本人是很喜欢.net的,并 ...
- 深入浅出WPF——附加事件(Attached Event)
3.3 事件也附加——深入浅出附加事件 WPF事件系统中还有一种事件被称为附加事件(Attached Event),简言之,它就是路由事件.“那为什么还要起个新名字呢?”你可能会问. “身无彩凤双飞翼 ...
- EsRejectedExecutionException排错与线程池类型
1.EsRejectedExecutionException异常示例 java.util.concurrent.ExecutionException: RemoteTransportException ...
- JavaScript适配器模式
适配模式可用来在现有接口和不兼容的类之间进行适配,使用这种模式的对象又叫包装器(wrapper),因为它们是在用一个新的接口包装另一个对象. 基本理论 适配器模式:将一个接口转换成客户端需要的接口而不 ...
- pm2部署多个nodejs项目配置教程
实际项目部署中,我们服务器在启动的时候需要自动启动node服务.以前是通过liunx自带的命令启动.但是随着后台微服务越来越多.每次发布新程序.修改脚本太麻烦了.于是换成PM2来做. 1.首先安装pm ...
- linux 计划任务(crontab)
每天写一点,总有一天我这条咸鱼能变得更咸 cron服务是一个linux下 的定时执行工具,可以在无需人工干预的情况下运行作业.频率可以划分为 分钟 小时 天 月 周,格式如下: 1.crontab 服 ...
- JS中apply和call的区别和用法
Javascript中有一个call和apply方法,其作用基本相同,但是它们也有略微不同的地方. JS手册中对call方法的解释是: call方法:调用一个对象的一个方法,以另一个对象替换当前对象. ...