PreparedStatement比Statement比别人有什么优势势

[转载]java中PreparedStatement与Statement相比具有什么优势
2.预编译PreparedStatement
使用范围:当执行相似sql语句的次数比较多(例如用户登陆,对表频繁操作..)语句一样,只是具体的值不一样,被称为动态SQL
优点:语句只编译一次,减少编译次数。提高了安全性(阻止了SQL注入)
缺点: 执行非相似SQL语句时,速度较慢。
原理:相似SQL只编译一次,减少编译次数
名词解释:
SQL注入:select * from user where username="张三" and password="123"
前面这条语句红色部分就是利用sql注入,使得这条词句使终都会返回一条记录,从而降低了安全性。
事例执行过程:
public void exec2(Connection conn){
Long beginTime = System.currentTimeMillis();
conn.setAutoCommit(false);//手动提交
PreparedStatement pst = conn.prepareStatement("insert into
t1(id) values (?)");
for(int i=0;i&10000;i ){
pst.setInt(1, i);
pst.execute();
Long endTime = System.currentTimeMillis();
System.out.println("Pst用时:" (endTime-beginTime) "秒");//计算时间
pst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
执行时间:Pst用时:14秒
3.使用PreparedStatement 批处理
使用范围:一次需要更新数据库表多条记录
优点:减少和SQL引擎交互的次数,再次提高效率,相似语句只编译一次,减少编译次数。提高了安全性(阻止了SQL注入)
批处理: 减少和SQL引擎交互的次数,一次传递给SQL引擎多条SQL。
名词解释:
PL/SQL引擎:在oracle中执行pl/sql代码的引擎,在执行中发现标准的sql会交给sql引擎进行处理。
SQL引擎:执行标准sql的引擎。
事例执行过程:
public void exec3(Connection conn){
conn.setAutoCommit(false);
Long beginTime = System.currentTimeMillis();
PreparedStatement pst = conn.prepareStatement("insert into
t1(id) values (?)");
for(int i=1;i&=10000;i ){
pst.setInt(1, i);
pst.addBatch();//加入批处理,进行打包
if(i00==0){//可以设置不同的大小;如50,100,500,1000等等
pst.executeBatch();
pst.clearBatch();
pst.executeBatch();
Long endTime = System.currentTimeMillis();
System.out.println("pst batch用时:" (endTime-beginTime) "毫秒");
pst.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
执行时间:pst batch用时:485毫秒
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。博客分类:
数据库在执行sql语句的时候如果使用PreparedStatement语句会有一点优势:因为数据库会PreparedStatement语句进行预编译,下次执行相同的sql语句时,数据库端不会再进行预编译了,而直接用数据库的缓冲区,提高数据访问的效率(但尽量尽量采用使用?号的方式传递参数),如果sql语句只执行一次,以后不再复用,则建议采用StatemenStatement不会对sql进行预编译。望高手补充!!
另外使用PS还有一个好处,不用对传入的字符串进行转义
PreparedStatement 能有效防止Sql注入攻击,速度较快,但失于灵活.
fengyaodong
浏览: 103844 次
来自: 北京
我发的顺丰
阿萨德阿萨德[b][/b]
卸载后,你是怎么修复那个软连接文件的?
我的是连错数据库了,连的那个数据库没有那个proc!呵呵,谢谢 ...关于PreparedStatement你知道多少
对应PreparedStatement相信大家都很熟悉,那么为什么要用PreparedStatement呢?也许你会回答PreparedStatement为预处理语句,可以提高执行效率。也许还会回答用PreparedStatement可以防止SQL注入。那么再问下,你觉得你对PreparedStatement有足够的了解吗,你在项目中PreparedStatement用对了吗?
首先来看下Statement及PreparedStatement执行过程,一个sql语句执行过程中,将经历这么几个步骤:
1、传输SQL给数据库
2、数据库验证并解析SQL
3、计算Access Plan。数据库会通过检测index,statistics来给出最优的访问计划。
4、根据访问计划进行检索,返回数据。
在上面步骤中,第3步是非常耗时的。因此,为了提高性能,数据库会缓存执行语句以及其Access Plan。这被称为statement cache。在statement cache中,sql语句本身为key,access plan为value。当相同的sql语句被发送过来时,数据库会使用缓存中的access plan以节省cpu时间。
下边看下Statement执行代码:
Statement statement = connection.createStatement();
String sql1=&Select * from test where id=1&;
String sql2=&Select * from test where id=&;
statement.execute(sql1);
statement.execute(sql1);
statement.execute(sql1);
statement.execute(sql2+&2&);
statement.execute(sql2+&3&);
sql1在第一次执行的时候,需要计算执行计划。但在第2和3次执行的时候,会使用缓存好的执行计划,因此后面的sql1不会再重新检验语法与计算执行计划,效率会比第一次高。
sql2却每次都在变化,在cache中,key为整个sql语句,所以每次sql2都无法命中cache,即使它仅仅参数不同,也必须重新检验语法与计算执行计划,效率自然就低下。
强大的数据库会在cache命中上做优化,但复杂的语句还是避免不了miss。
PreparedStatement的存在是为了避免sql2的劣势。看下面code。
String sql2=&Select * from test where id=?&;
PreparedStatement pstmt = connection.prepareStatement(sql2);
pstmt.setInt(1,2);
pstmt.executQuery();
pstmt.setInt(1,3);
pstmt.executQuery();
PreparedStatement在创建的时候,会将参数化的语句发送给数据库,进行语法检测和执行计划计算。Cache中的key将是参数化的语句。当后面preparedstatement在执行的时候,每次均会命中cache,使用已存在的access plan进行检索。
如何正确使用
PreparedStatement的生命周期跟Statement一样,在一个数据库连接connection范围内有效,所以说如果一次连接中对于同一个PreparedStatement处理多次(参数不同),那么用PreparedStatement是可以提高效率,但大多情景都是多次连接中处理同一个PreparedStatement,那么就算使用了PreparedStatement也不能提高效率,比较PreparedStatement的生命周期只在Connection中。那么如何正确的使用PreparedStatement呢?
其实不用紧张,告诉大家个好消息,J2EE服务器的连接池管理器已经实现了缓存的使用。J2EE服务器保持着连接池中每一个连接准备过的prepared statement列表。当我们在一个连接上调用preparedStatement时,应用服务器会检查这个statement是否曾经准备过。如果是,这个PreparedStatement会被返回给应用程序。如果否,调用会被转给JDBC驱动程序,然后将新生成的statement对象存入连接缓存。
如果项目未使用数据库连接池怎么办呢,这里只能告诉你,原理你已经很清楚了,自己实现吧。PreparedStatement是如何大幅度提高性能的PreparedStatement是如何大幅度提高性能的 PreparedStatement&Billy Newport&prepared statements&&Prepared Statements&SQLstatementsPrepared StatementsPrepared Statements&&statement&statementstatementstatementstatement&Access PlanCPUstatementstatementCPU&&Statement Caches&statementstatementkeystatementstatementsSELECT a, b FROM t WHERE c = 2statementstatementCPU&statementkeySELECT a, b FROM t WHERE c = 3statementc=3c=2&for (int i = 0; i & 1000; i++) &{PreparedStatement ps = conn.prepareStatement("select a,b from t where c = " + i);ResultSet rs = Ps.executeQuery();rs.close();ps.close();}&在这里缓存不会被使用,因为每一次迭代都会发送一条包含不同SQL语句的statement给数据库。并且每一次迭代都会生成一个新的存取方案。现在让我们来看看下一段代码:&PreparedStatement ps = conn.prepareStatement("select a,b from t where c = ");for (int i = 0; i & 1000; i++) &{ps.setInt(1, i);ResultSet rs = ps.executeQuery();rs.close();ps.close();}&这样就具有了更好的效率,这个statement发送给数据库的是一条带有参数“?”的SQL语句。这样每次迭代会发送相同的statement到数据库,只是参数“c=”不同。这种方法允许数据库重用statement的存取方案,这样就具有了更好的效率。这可以让你的应用程序速度更快,并且使用更少的CPU,这样数据库服务器就可以为更多的人提供服务。&&PreparedStatement与J2EE服务器&当我们使用J2EE服务器时事情会变的比较复杂。通常,一个perpared statement会同一个单独的数据库连接相关联。当数据库连接被关闭时prepared statement也会被丢弃。通常,一个胖客户端会获取一个数据库连接并将其一直保持到退出。它会用“饿汉”(eagerly)或“懒汉”(lazily)方式创建所有的parepared statements。“饿汉”方式会在应用启动时创建一切。“懒汉”方式意味着只有在使用的时候才去创建。“饿汉”方式会使应用程序在启动的时候梢有延迟,但一旦启动后就会运行的相当理想。“懒汉”方式使应用程序启动速度非常快(但不会做任何准备工作),当需要使用prepared statement的时候再去创建。这样,在创建全部statement的过程中,性能是非常不稳定的,但一旦创建了所有statement后,它会像“饿汉”式应用程序一样具有很好的运行效果。请根据你的需要来选择最好的方式,是快速启动?还是前后一致的性能。&J2EE应用的问题是它不会像这样工作,连接只会在请求期间被保持。那意味着必须每一次请求的时候都创建prepared statement。这远没有胖客户端那种一直保持prepared statement的执行性能好。J2EE厂商已经注意到了这个问题,并且提供了连接池(ConnectionPool)以避免这种问题。&当J2EE服务器提供了一个连接给你的应用程序时,其实它并没有给你真正的数据库连接,你只是获得了一个包装器(Wrapper)。你可以去看看你所获得的连接的类名以证实这一点。它并不是一个JDBC连接,而是一个由应用服务器创建的类。所有的JDBC操作都会被应用服务器的连接池管理器所代理。所有的JDBC ResultSets,statements,CallableStatements,preparedStatements等都会被包装并以一个“代理对象”(Proxy Object)的形式返回给应用程序。当你关闭了连接,这些对象会被标记为失效,并被垃圾回收器所回收。&通常,如果你对一个数据库连接执行close,那这个连接会被JDBC驱动程序关闭。但我们需要在J2EE服务器执行close的时候数据库连接会被返回连接池。我们可以创建一个像真正的连接一样的JDBC Connection代理类来解决这个问题。它有一个对真正连接的引用。当我们执行一个连接上的方法时,代理会将操作转给真正的连接。但是,当我们对一个连接执行close时,这个连接并不会关闭,而是会送回连接池,并可以被其他请求所使用。一个已被准备过的prepared statement也会因此而得到重用。&&J2EE PreparedStatement Cache&J2EE服务器的连接池管理器已经实现了缓存的使用。J2EE服务器保持着连接池中每一个连接准备过的prepared statement列表。当我们在一个连接上调用preparedStatement时,应用服务器会检查这个statement是否曾经准备过。如果是,这个PreparedStatement会被返回给应用程序。如果否,调用会被转给JDBC驱动程序,然后将新生成的statement对象存入连接缓存。&每个连接都有一个缓存的原因是因为:JDBC驱动程序就是这样工作的。任何prepared statement都是由指定的连接所返回的。&如果我们想利用这个缓存的优势,那就如前面所说的,使用参数化的查询语句可以在缓存中找到曾经使用过的statement。大部分应用服务器允许你调整prepared statements缓存的大小。&&摘要&我们绝对应该使用包含参数化的查询语句的prepared statement。这样数据库就会重用准备过的存取方案。缓存适用于整个数据库,所以,如果你安排所有的应用程序使用相同的参数化SQL语句,然后你的其他应用程序就可以重用被准备过的prepared statement。这是应用服务器的一个优势,因为所有的数据库操作都集中在数据库操作层(Database Access Layer,包括O/R映射,实体Bean,JDBC等)。&第二,正确的使用prepared statement也是利用prepared statement的缓存优势的关键。由于应用程序可以重用准备过的prepared statement,也就减少了调用JDBC驱动程序的次数,从而提高了应用程序的性能。这样就拥有了可以与胖客户端比肩的效率,却又不需要总维持一个连接。&使用参数化的prepared statement,你的应用程序会具有更好的性能。 &本帖子已过去太久远了,不再提供回复功能。}

我要回帖

更多关于 女生比男生有优势辩论 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信