`
ikon
  • 浏览: 107199 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

PreparedStatement的预编译

    博客分类:
  • java
阅读更多

一、我们先来看一下sql的执行过程:
在Oracle里执行一个SQL语句,一般都要经过下面几个步骤:
 Create a Cursor 创建游标;
 Parse the Statement 解析语句;
 Bind Any Variables 绑定变量;
 Run the Statement 运行语句;
 Close the Cursor 关闭游标;
如果是一个查询SQL,则还要经过下面的步骤:
 Describe Results of a Query 描述查询的结果集;
 Define Output of a Query 定义查询的输出数据;
 Fetch Rows of a Query 获取查询出来的行。

二、SQL解析过程
从上面的步骤可以看出,每执行一个SQL,都需要对它进行解析(Parse),而一个解析过程,需要完成下面的工作:
 语法检查,验证它是否是合法的语句,有没有语法错误;
 语义检查,实现数据字典的查找,以验证是否符合表和列的定义,类型是否正确;
 (如果是CBO优化模式,关于CBO,请看后面Oracle的优化器一章)收集参考对象的统计;
 在所要求的对象上获取语法分析锁,使得在语句的语法分析过程中不改变这些对象的定义;
 检查用户的权限是否足够;
 从许多可能的执行路径中选择此语句最佳的执行计划;
 将它装入共享SQL区;
 生成语句的编译版本(P-CODE)。
解析是一个昂贵的操作,因为解析过程中需要消耗许多资源,而且费时,正因为如此,Oracle创造了共享池的概念,共享池会自动将解析过的SQL缓存起来,以后碰到相同的SQL,就不用再解析了,这样可以大大提高SQL的执行速度。

三、 缓存SQL的原理
ORACLE执行SQL语句时,先将SQL语句的字串通过一个hash算法得出一个hash值,然后检查共享池中是否已存在这个哈希值,若有就用已缓存的执行计划来执行这个语句(即缓存命中,后面我们会提到共享池的命中率,就是这个概念),若没有(即缓存缺失)则需进行解析。
由于Oracle是通过SQL字符的hash值来判断是否为相同的SQL语句,因此,如果你的SQL有一点小小的变换,在Oracle看来,就是另外一个SQL了,会对它进行重新解析。
例如:

  1. select id, name from members where id = 1403   
  2. select id, name From members where id = 1403   
  3. select name, id from members where id = 1403  

这三条SQL在Oracle看来就是三条不同的SQL。

 绑定变量

在大部分时候,sql语句里有一些经常会变化的值。例如:

  1. select id, name from members where id = 1207   
  2. select id, name from members where id = 1208   
  3. select id, name from members where id = 1209  

前面说过了,这样的SQL其实是三条不同的SQL,因为它们的字符明显不一样。那我们该怎么样才能让它们成为同一条SQL呢?可以通过绑定变量来实现。
下面是一条含绑定变量的sql 语句:

  1. select id, name from members where id = :member_id  

这样不管member_id如何变化,Oracle都会认为这条SQL是同一条,就可以节省解析的成本了。
那么,在java开发中,怎么使用绑定变量呢?注意,不要认为下面的代码是在使用绑定变量:

  1. Statement stmt=conn.createStatement();   
  2. String member_id=member.id;   
  3. String sql="select id,name from members where id ="+member_id;   
  4. stmt.executeQuery(sql);  

上面的例子里,当member.id的值为1207时,我们传给stmt的SQL实际上是:

  1. select id, name from members where id = 1207  

当member.id的值为1208时,就是:

  1. select id, name from members where id = 1208  

它们在Oracle看来仍然是不同的SQL。
其实,在java中使用绑定变量非常简单,只需要使用PreparedStatement对象就可以了。如下:

  1. String sql="select id,name from members where id =?";   
  2. PreparedStatement pstmt=conn.createStatement(sql);   
  3. pstmt.setString(1,member.id);//将member.id传给第一个问号。  

这样,PreparedStatement会自动把这条SQL在传给Oracle时转化为类似下面的SQL:

  1. select id, name from members where id = :member_id  

这样就实现了绑定变量,它只需解析一次,不管member.id如何变化,都不用再做解析了。

分享到:
评论

相关推荐

    spring自带的jdbcTemplate查询、插入预编译使用

    首先,`jdbcTemplate`的核心功能是通过预编译的SQL语句(PreparedStatement)来执行数据库操作。预编译SQL可以有效防止SQL注入,提高代码的可读性和执行效率。在使用`jdbcTemplate`进行预编译查询时,我们通常会使用...

    MySQL预编译功能

    使用 PreparedStatement 也可以实现预编译功能,例如: Connection con = JdbcUtils.getConnection(); String sql = "select * from t_book where bid=?"; PreparedStatement pstmt = con.prepareStatement(sql); ...

    SQL.预编译.docx

    预编译语句,即PreparedStatement,是Java.sql包中的一个接口,它是Statement接口的子接口。与普通的Statement对象不同,PreparedStatement在创建时就需要提供SQL语句,并立即发送到数据库进行编译。当执行时,...

    JAVA预编译示例代码

    本文提供了一个 JAVA 预编译示例代码,涵盖了预编译中使用 like、javaSQL 预编译异常、预编译语句支持 in 方式等多个方面的知识点。 1. 预编译中使用 like 在预编译中使用 like 时,需要在值的地方加 % 号,以便...

    PreparedStatement 马克-to-win java视频

    PreparedStatement 预编译statement 的详细介绍java视频 马克java社区 马克-to-win

    MySQL 事务预编译查询和Perl DBI简化

    预编译查询是MySQL提供的一种优化机制,通过PreparedStatement接口实现。预编译查询可以提高性能,因为它允许数据库解析SQL语句一次,然后多次执行该语句,只需改变参数即可。这减少了解析时间,并且可以防止SQL注入...

    数据库连接

    这是因为PreparedStatement预编译SQL语句,使得数据库可以提前解析和优化,从而提高性能。对于异构的SQL(结构不同的查询),Statement的执行效率可能较高,因为它没有预编译过程。 4. **参数绑定** ...

    java_JDBC预编译相关知识点参照.pdf

    预编译语句(PreparedStatement)是Java编程语言中用于与数据库交互的一个重要概念,它是java.sql包中的一个接口,是Statement接口的子接口。预编译语句的设计旨在提高SQL语句的执行效率和安全性,尤其是在需要频繁...

    JAVA-Web阶段重点及面试题汇总.pdf

    - PreparedStatement预编译SQL语句,适用于执行多次的SQL操作,提升效率,且有防止SQL注入的安全性。 - 防SQL注入:PreparedStatement将参数作为值处理,而非字符串拼接,避免恶意输入破坏SQL结构。 - 可读性好:...

    JDBC之PreparedStatement类中预编译的综合应用解析

    PreparedStatement是Java JDBC中用于执行预编译SQL语句的接口,它是Statement的子接口。预编译的SQL语句可以提高数据库操作的性能和安全性。在数据库系统中,预编译意味着SQL语句在首次执行前已经过编译,形成一个...

    Java之JDBC连接MySQL数据库实现增删改查(2018 使用Dao层实现 完美封装解决硬编码问题 使用预编译对象PreparedStatement)

    Java之JDBC连接数据库实现增删改查(2018 使用Dao层实现 完美封装解决硬编码问题 使用预编译对象PreparedStatement) 配置文件 db.properties(保存数据库账号和密码等) 工具类 JDBCUtil.java(抽取公共部分,解决硬...

    基于servlet+jsp+jdbc的在线考试管理系统 .zip

    为了优化数据库操作,通常会使用PreparedStatement预编译SQL,减少SQL注入风险,并使用Connection池管理数据库连接。 **系统架构与流程** 1. 用户通过浏览器发送HTTP请求到Web服务器。 2. Web服务器接收到请求后,...

    MySQL数据库

    - PreparedStatement预编译的SQL执行对象 1. 可以避免SQL注入 因为在编译的时候已经把SQL的逻辑固定,不会因为替换进去的内容改变逻辑 2. 如果SQL中涉及变量 相比Statement的字符串拼接的方式,代码可读性提高,并且...

    分别使用JDBC、SQL Developer访问Oracle的一点区别

    PreparedStatement预编译SQL,更安全且性能更好;ResultSet存储查询结果。 - JDBC编程通常涉及加载驱动、建立连接、创建Statement或PreparedStatement对象、执行SQL和关闭资源。 2. SQL Developer: - SQL ...

    一文搞懂MySQL预编译

    在Java中,可以使用PreparedStatement接口实现MySQL预编译。以下是一个简单的示例: ```java Connection con = JdbcUtils.getConnection(); String sql = "select * from t_book where bid=?"; PreparedStatement ...

    Java数据库技术详解 DOC简版

    6.1 PreparedStatement预编译对象 6.2 CallableStatement存储过程对象 6.3 BatchedUpdate对象 6.4 Rowset行集合对象 6.5 JDBC的事务 6.6 本章小结 第7章 JDBC结合Servlet与JSP 的应用 7.1 Servlet概述...

    一点关于JDBC的内容

    2. **预编译SQL**:PreparedStatement预编译SQL语句,提升执行效率。 3. **连接池**:使用连接池(如C3P0、HikariCP)管理数据库连接,避免频繁创建和关闭连接。 4. **使用PreparedStatement代替Statement**:防止...

    《SQL预编译和批量提交对性能提升效果探索》测试代码

    例如,在Java的JDBC中,我们可以使用PreparedStatement对象来实现预编译,它的优点在于减少解析和编译SQL语句的时间,提升执行速度。 接着,我们来讨论批量提交。在传统的数据库操作中,每次插入、更新或删除操作...

    javaSE面试题

    - **性能**:PreparedStatement预编译SQL,执行效率更高,因为数据库只需要解析一次SQL,后续执行无需再编译。 - **代码可读性**:PreparedStatement使用占位符"?",使SQL与参数分离,便于维护和避免SQL注入。 3....

    java日期和查询数据库生成XML文件类

    - 避免硬编码SQL语句,使用PreparedStatement预编译SQL,提高安全性。 - 使用try-with-resources语句管理数据库连接,确保资源及时关闭。 - 对于大型XML文件,考虑使用SAX避免内存溢出。 - 将日期格式化逻辑封装...

Global site tag (gtag.js) - Google Analytics