JDBC之Statement,PreparedStatement,CallableStatement的差异牛牛娱乐 - 牛牛娱乐

JDBC之Statement,PreparedStatement,CallableStatement的差异牛牛娱乐

2019年02月16日07时24分16秒 | 作者: 浅秋 | 标签: 参数,办法,目标 | 浏览: 16077

Statement 每次履行sql句子,数据库都要履行sql句子的编译 ,最好用于仅履行一次查询并回来成果的景象,功率高于PreparedStatement.



PreparedStatement是预编译的,运用PreparedStatement有几个优点

a. 在履行可变参数的一条SQL时,PreparedStatement比Statement的功率高,由于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程序发生很多的Statement和PreparedStatement目标。一般以为PreparedStatement目标比Statement目标更有用,特别是假如带有不同参数的同一SQL句子被屡次履行的时分。PreparedStatement目标答应数据库预编译SQL句子,这样在随后的运转中能够节省时刻并添加代码的可读性。

但是,在Oracle环境中,开发人员实践上有更大的灵活性。当运用Statement或PreparedStatement目标时,Oracle数据库会缓存SQL句子以便今后运用。在一些情况下,由于驱动器本身需求额定的处理和在Java应用程序和Oracle服务器间添加的网络活动,履行PreparedStatement目标实践上会花更长的时刻。

但是,除了缓冲的问题之外,至少还有一个更好的原因使咱们在企业应用程序中更喜爱运用PreparedStatement目标,那就是安全性。传递给PreparedStatement目标的参数能够被强制进行类型转化,使开发人员能够保证在刺进或查询数据时与底层的数据库格局匹配。

当处理公共Web站点上的用户传来的数据的时分,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会主动被驱动器疏忽。最简略的情况下,这就意味着当你的程序试着将字符串“DAngelo”刺进到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(?, ?)}");


其间?占位符为IN、OUT仍是INOUT参数,取决于已贮存进程getTestData。

2、IN和OUT参数

将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);



3、INOUT参数

既支撑输入又承受输出的参数(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);


版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表牛牛娱乐立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章