`

JDBC之Statement,PreparedStatement,CallableStatement的区别

阅读更多

 

 

http://blog.csdn.net/ystyaoshengting/article/details/6200579

 

Statement 每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement.

 

PreparedStatement是预编译的,使用PreparedStatement有几个好处

 a. 在执行可变参数的一条SQL时,PreparedStatementStatement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。

 b. 安全性好,有效防止Sql注入等问题。

 c.  对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch

 d.  代码的可读性和可维护性。

 

CallableStatement接口扩展 PreparedStatement,用来调用存储过程,它提供了对输出和输入/输出参数的支持。CallableStatement 接口还具有对 PreparedStatement 接口提供的输入参数的支持。

 

 

 

用法介绍

 

statement 1:


String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′";
stmt.executeUpdate(updateString);

preparedstatement 2:

PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();

片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。
这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。

5.执行许多SQL语句的JDBC程序产生大量的StatementPreparedStatement对象。通常认为PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。

然而,在Oracle环境中,开发人员实际上有更大的灵活性。当使用StatementPreparedStatement对象时,Oracle数据库会缓存SQL语句以便以后使用。在一些情况下,由于驱动器自身需要额外的处理和在Java应用程序和Oracle服务器间增加的网络活动,执行PreparedStatement对象实际上会花更长的时间。

然而,除了缓冲的问题之外,至少还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。

当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽略。最简单的情况下,这就意味着当你的程序试着将字符串“D'Angelo”插入到VARCHAR2中时,该语句将不会识别第一个,从而导致悲惨的失败。几乎很少有必要创建你自己的字符串忽略代码。

Web环境中,有恶意的用户会利用那些设计不完善的、不能正确处理字符串的应用程序。特别是在公共Web站点上,在没有首先通过PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。此外,在用户有机会修改SQL语句的地方,如HTML的隐藏区域或一个查询字符串上,SQL语句都不应该被显示出来。

 

 

 

 

 

callablestatement 使用方法

JDBC 中调用已储存过程的语法如下所示。

{call 过程名[(?, ?, ...)]}


  返回结果参数的过程的语法为:

{? = call 过程名[(?, ?, ...)]}


  不带参数的已储存过程的语法类似:

{call 过程名}


  通常,创建 CallableStatement 对象的人应当知道所用的 DBMS 是支持已储存过程的,并且知道这些过程都是些什么。然而,如果需要检查,多种DatabaseMetaData 方法都可以提供这样的信息。例如,如果 DBMS 支持已储存过程的调用,则supportsStoredProcedures 方法将返回 true,而getProcedures 方法将返回对已储存过程的描述。CallableStatement 继承 Statement 的方法(它们用于处理一般的 SQL 语句),还继承了 PreparedStatement 的方法(它们用于处理 IN 参)。

  CallableStatement 中定义的所有方法都用于处理 OUT 参数或 INOUT 参数的输出部分:注册 OUT 参数的 JDBC 类型(一般 SQL 类型)、从这些参数中检索结果,或者检查所返回的值是否为 JDBC NULL

  1、创建 CallableStatement 对象 

  CallableStatement 对象是用 Connection 方法 prepareCall 创建的。下例创建 CallableStatement 的实例,其中含有对已储存过程 getTestData 调用。该过程有两个变量,但不含结果参数:

CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");


  其中?占位符为INOUT还是INOUT参数,取决于已储存过程getTestData

  2INOUT参数 

  将IN参数传给 CallableStatement 对象是通过 setXXX 方法完成的。该方法继承自 PreparedStatement。所传入参数的类型决定了所用的setXXX方法(例如,用 setFloat 来传入 float 值等)。

  如果已储存过程返回 OUT 参数,则在执行 CallableStatement 对象以前必须先注册每个 OUT 参数的 JDBC 类型(这是必需的,因为某些 DBMS 要求 JDBC 类型)。注册 JDBC 类型是用 registerOutParameter 方法来完成的。语句执行完后,CallableStatement getXXX 方法将取回参数值。正确的 getXXX 方法是为各参数所注册的 JDBC 类型所对应的 Java 类型。换言之, registerOutParameter 使用的是 JDBC 类型(因此它与数据库返回的 JDBC 类型匹配),而 getXXX 将之转换为 Java 类型。

  作为示例,下述代码先注册 OUT 参数,执行由 cstmt 所调用的已储存过程,然后检索在 OUT 参数中返回的值。方法 getByte 从第一个 OUT 参数中取出一个 Java 字节,而 getBigDecimal 从第二个 OUT 参数中取出一个 BigDecimal 对象(小数点后面带三位数):

 

CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
cstmt.executeQuery();
byte x = cstmt.getByte(1);
java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);

 

3INOUT参数 

  既支持输入又接受输出的参数(INOUT 参数)除了调用 registerOutParameter 方法外,还要求调用适当的 setXXX 方法(该方法是从 PreparedStatement 继承来的)。setXXX 方法将参数值设置为输入参数,而 registerOutParameter 方法将它的 JDBC 类型注册为输出参数。setXXX 方法提供一个 Java 值,而驱动程序先把这个值转换为 JDBC 值,然后将它送到数据库中。这种 IN 值的 JDBC 类型和提供给 registerOutParameter 方法的 JDBC 类型应该相同。然后,要检索输出值,就要用对应的 getXXX 方法。例如,Java 类型为byte 的参数应该使用方法 setByte 来赋输入值。应该给registerOutParameter 提供类型为 TINYINT JDBC 类型,同时应使用 getByte 来检索输出值。

  下例假设有一个已储存过程 reviseTotal,其唯一参数是 INOUT 参数。方法setByte 把此参数设为 25,驱动程序将把它作为 JDBC TINYINT 类型送到数据库中。接着,registerOutParameter 将该参数注册为 JDBC TINYINT。执行完该已储存过程后,将返回一个新的 JDBC TINYINT 值。方法 getByte 将把这个新值作为 Java byte 类型检索。

CallableStatement cstmt = con.prepareCall("{call reviseTotal(?)}");
cstmt.setByte(1, 25);
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.executeUpdate();
byte x = cstmt.getByte(1);

 

原文地址:http://lapulande.javaeye.com/blog/585424

 

 

 

分享到:
评论

相关推荐

    JDBC入门学习简单教程

    JDBC学习的简单教程,包括如何连接数据库,使用Statement,PreparedStatement,CallableStatement,元数据等。 主要用于教学和自学

    jdbc连接数据库的方式2

    Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用...

    JDBC笔记 JDBC笔记

    java.sql.PreparedStatement 继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。然后可以使用此对象高效地多次执行该语句。 java.sql.CallableStatement 用来...

    JDBC 3.0数据库开发与设计

    4.1.1 PreparedStatement对象的创建 4.1.2 传递IN参数 4.1.3 传递对象参数 4.1.4 传递大型数据参数 4.2 调用存储过程对象 4.2.1 CallableStatement对象的创建 4.2.2 IN、OUT及INOUT参数的使用 4.2.3 执行...

    java jbdc 技术编程文档

    Java的数据库连接编程(JDBC)技术 [知识要点]:JDBC、JDBC的工作原理,访问数据库的方法、Statement、PreparedStatement、CallableStatement,ResultSet等对象的编程使用

    Java_JDBC由浅入深

    第九节 PreparedStatement接口的使用 62 第十节 CallableStatement接口的使用 62 9.1 无参无返回值存储过程调用 63 9.2 有参无返回值存储过程调用 63 9.3 有参有返回值存储过程调用 64 9.4 JDBC其他API 65 第十一节 ...

    jdbc基础和参考

    //分别使用Statement对象和PreparedStatement对象实现 public class JDBCTest{ //查找s_user表中所有的数据,并且返回他们的集合 public Collection<User> findAll(){ } //按照名字进行删除 public int ...

    java业务层框架开发ibatis(java源码)

    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null;} public CallableStatement prepareCall...

    JDBC执行SQL操作.docx

    利用Statement实例通过执行静态SELECT语句完成,也可以利用PreparedStatement实例通过执行SELECT语句进行完成,还可以利用CallableStatement实例通过执行存储过程来完成。 (1)利用Statement实例通过执行静态...

    java面向对象核心知识点,独门大法

    每一个知识点的讲解,都会包含语法,语法个数如何定义,然后语法下面就是使用方式,能够起到活学活用的帮助,比如在讲解jdbc的时候我会列举出来 Statement(执行简单的sql语句,不支持预编译) PreparedStatement...

    Java数据库编程宝典2

    第13章 使用PreparedStatement和CallableStatement 13.1 创建和使用PreparedStatement 13.1.1 创建PreparedStatement对象 13.1.2 在循环中使用PrenaredStatement 13.1.3 PreparedStatement返回的值 13.2 创建...

    Java数据库编程宝典4

    第13章 使用PreparedStatement和CallableStatement 13.1 创建和使用PreparedStatement 13.1.1 创建PreparedStatement对象 13.1.2 在循环中使用PrenaredStatement 13.1.3 PreparedStatement返回的值 13.2 创建...

    Java数据库编程宝典1

    第13章 使用PreparedStatement和CallableStatement 13.1 创建和使用PreparedStatement 13.1.1 创建PreparedStatement对象 13.1.2 在循环中使用PrenaredStatement 13.1.3 PreparedStatement返回的值 13.2 创建...

    Java数据库编程宝典3

    第13章 使用PreparedStatement和CallableStatement 13.1 创建和使用PreparedStatement 13.1.1 创建PreparedStatement对象 13.1.2 在循环中使用PrenaredStatement 13.1.3 PreparedStatement返回的值 13.2 创建...

    java经典面试2010集锦100题(不看你后悔)

    B) 重载方法的参数必须有不同之处。 C) 重载方法的名字必须相同,否则就不能称为重载了。 D) 重载方法的返回类型相不相同都可以。 题目23:d 程序如下: class A { static int count=0; int number=0; A() { ...

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

    14.1.4 使用preparedstatement、callablestatement 469 14.2 jdbc进阶 472 14.2.1 使用datasource取得联机 472 14.2.2 使用resultset卷动、更新数据 476 14.2.3 批次更新 479 14.2.4 blob与clob 480 ...

Global site tag (gtag.js) - Google Analytics