以下内容引用自http://wiki.jikexueyuan.com/project/jdbc/stored-procedure.html

正如一个Connection对象创建了Statement和PreparedStatement对象,它也创造了在数据库中被执行调用的CallableStatement对象。

一、创建CallableStatement对象

假设,需要执行下面的Oracle存储过程:

CREATE OR REPLACE PROCEDURE getEmpName
(EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS
BEGIN
SELECT first INTO EMP_FIRST
FROM Employees
WHERE ID = EMP_ID;
END;

注意:上面的存储过程是在Oracle使用的,但使用的是MySQL数据库,所以在MySQL的环境下需要重新写出相同功能的代码,下面的代码是在EMP数据库中创建相同功能的代码:

DELIMITER $$

DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$
CREATE PROCEDURE `EMP`.`getEmpName`
(IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
SELECT first INTO EMP_FIRST
FROM Employees
WHERE ID = EMP_ID;
END $$ DELIMITER ;

当前有三种类型的参数:IN,OUT和INOUT。PreparedStatement对象只能使用IN参数。CallableStatement对象可以使用所有的三种类型。

下面是三种类型参数的定义:

参数 描述
IN 当SQL语句创建的时候,该参数的值是未知的。可以用setXXX()方法将值绑定到IN参数里。
OUT 该参数的值是由SQL语句的返回值。可以用getXXX()方法从OUT参数中检索值。
INOUT 该参数同时提供输入和输出值。可以用setXXX()方法将值绑定到IN参数里,并且也可以用getXXX()方法从OUT参数中检索值。

下面的代码片段展示了如何使用Connection.prepareCall()方法实现一个基于上述存储过程的CallableStatement对象:

CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall(SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}

字符串变量SQL使用参数占位符来表示存储过程。

使用CallableStatement对象就像使用PreparedStatement对象。在执行该语句前,必须将值绑定到所有的参数,否则将收到一个SQL异常。

如果有IN参数,只要按照适用于PreparedStatement对象相同的规则和技巧;用setXXX()方法来绑定对应的Java数据类型。

当使用OUT和INOUT参数就必须采用额外的CallableStatement方法:registerOutParameter()。registerOutParameter()方法将JDBC数据类型绑定到存储过程返回的数据类型。

一旦调用了存储过程,可以用适当的getXXX()方法从OUT参数参数中检索数值。这种方法将检索出来的SQL类型的值映射到Java数据类型。

二、关闭CallableStatement对象

正如关闭其它的Statement对象,出于同样的原因,也应该关闭CallableStatement对象。

close()方法简单的调用就可以完成这项工作。如果先关闭了Connection对象,那么它也会关闭CallableStatement对象。然而,应该始终明确关闭CallableStatement对象,以确保该对象被彻底关闭。

CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall(SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
cstmt.close();
}

示例:

创建存储过程:

DELIMITER $$

DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$
CREATE PROCEDURE `EMP`.`getEmpName`
(IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
SELECT first INTO EMP_FIRST
FROM Employees
WHERE ID = EMP_ID;
END $$ DELIMITER ;

JDBCExample:

//STEP 1. Import required packages
import java.sql.*; public class JDBCExample {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/Test?serverTimezone=UTC"; // Database credentials
static final String USER = "root";
static final String PASS = "root"; public static void main(String[] args) {
Connection conn = null;
CallableStatement stmt = null;
try {
// STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver"); // STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL, USER, PASS); // STEP 4: Execute a query
System.out.println("Creating statement...");
String sql = "{call getEmpName (?, ?)}";
stmt = conn.prepareCall(sql); // Bind IN parameter first, then bind OUT parameter
int empID = 102;
stmt.setInt(1, empID); // This would set ID as 102
// Because second parameter is OUT so register it
stmt.registerOutParameter(2, java.sql.Types.VARCHAR); // Use execute method to run stored procedure.
System.out.println("Executing stored procedure...");
stmt.execute(); // Retrieve employee name with getXXX method
String empName = stmt.getString(2);
System.out.println("Emp Name with ID:" + empID + " is " + empName);
stmt.close();
conn.close();
} catch (SQLException se) {
// Handle errors for JDBC
se.printStackTrace();
} catch (Exception e) {
// Handle errors for Class.forName
e.printStackTrace();
} finally {
// finally block used to close resources
try {
if (stmt != null)
stmt.close();
} catch (SQLException se2) {
} // nothing we can do
try {
if (conn != null)
conn.close();
} catch (SQLException se) {
se.printStackTrace();
} // end finally try
} // end try
System.out.println("Goodbye!");
}// end main
}// end JDBCExample

这将产生如下所示结果:

三、JDBC的SQL转义语法

转义语法使能够通过使用标准的JDBC方法和属性,来灵活的使用数据库的某些特定功能,而该特定功能来说本来是不可用的。

常用的SQL转义语法格式如下所示:

{keyword 'parameters'}

当在编程的时候,会发现以下的这些转义序列会非常有用的:

1、d,t,ts关键字

它们能帮助确定日期,时间和时间戳的文字。众所周知,没有两个数据库管理系统的时间和日期的表现方式是相同的。该转义语法告诉驱动程序以目标数据库的格式来呈现日期或时间。例如:

{d 'yyyy-mm-dd'}

其中yyyy=年,mm=月,DD=日。使用这种语法{d '2009-09-03'}即是2009年3月9日。

下面是一个说明如何在表中插入日期的简单例子:

//Create a Statement object
stmt = conn.createStatement();
//Insert data ==> ID, First Name, Last Name, DOB
String sql="INSERT INTO STUDENTS VALUES" + "(100,'Zara','Ali', {d '2001-12-16'})"; stmt.executeUpdate(sql);

同样的,可以使用以下两种语法之一,无论是t或ts:

{t 'hh:mm:ss'}

其中hh=小时,mm=分,ss=秒。使用这种语法{t '13:30:29'}即是下午1点30分29秒。

{ts 'yyyy-mm-dd hh:mm:ss'}

这是用上述两种语法'd'和't'表示时间戳的组合语法。

2、escape关键字

该关键字在LIKE子句中使用,来定义转义字符。当使用SQL通配符%,来匹配零个或多个字符时,该关键字就非常有用。例如:

String sql = "SELECT symbol FROM MathSymbols WHERE symbol LIKE '\%' {escape '\'}";
stmt.execute(sql);

如果使用反斜杠字符(\)作为转义字符,必须在Java字符串里使用两个反斜杠字符,因为反斜杠也是一个Java转义字符。

3、fn关键字

该关键字代表在数据库管理系统中使用标量函数。例如,可以使用SQL的length函数来计算字符串的长度:

{fn length('Hello World')}

这将返回11,也就是字符串'Hello World'的长度。

4、call关键字

该关键字是用来调用存储过程的。例如,对于一个需要一个IN参数的存储过程,使用以下语法:

{call my_procedure(?)};

对于需要一个IN参数并返回一个OUT参数的存储过程,使用下面的语法:

{? = call my_procedure(?)};

5、oj关键字

该关键字用来表示外部连接,其语法如下所示:

{oj outer-join}

其中outer-join=表{LEFT|RIGHT|FULL}OUTER JOIN{表|outer-join}的搜索条件。例如:

String sql = "SELECT Employees  FROM {oj ThisTable RIGHT OUTER JOIN ThatTable on id = '100'}";
stmt.execute(sql);
 

JDBC的存储过程的更多相关文章

  1. Java数据库连接——JDBC调用存储过程,事务管理和高级应用

    一.JDBC常用的API深入详解及存储过程的调用 相关链接:Jdbc调用存储过程 1.存储过程(Stored Procedure)的介绍 我们常用的操作数据库语言SQL语句在执行的时候需要先编译,然后 ...

  2. jdbc调用存储过程的方法

    ----------------------------jdbc调用存储过程的方法---------------------------------------------------private ...

  3. JDBC调用存储过程

    一. JDBC调用存储过程 (1)使用存储过程SQL编写的程序代码,等一段语句和控制流语句.在创建时被编译成机器代码和存储在数据库中的client转让. 存储过程具有以下优势: 1.所生成的机器代码被 ...

  4. Java数据库连接--JDBC调用存储过程,事务管理和高级应用

    相关链接:Jdbc调用存储过程 一.JDBC常用的API深入详解及存储过程的调用 1.存储过程的介绍 我们常用的操作数据库语言SQL语句在执行的时候要先进行编译,然后执行,而存储过程是在大型数据库系统 ...

  5. JDBC调用存储过程的例子

    下面是我学到了Oracle存储过程,在这里跟大家简单的分享一下利用JDBC调用存储过程的例子: 废话就不啰嗦,现在就直接上机代码. 首先我利用的是Oracle中默认的 scott 数据库里的 emp员 ...

  6. JDBC(13)—JDBC调用存储过程和函数

    步骤: JDBC调用存储过程和函数 步骤: ①:通过Connection对象的prepareCall()方法创建一个CallableStatement对象的实例,在使用Connection对象的pre ...

  7. Java JDBC调用存储过程:无参、输入带参、输出及输出带参

    Java JDBC调用存储过程:无参.输入带参.输出及输出带参 示例代码: package xzg; import java.sql.CallableStatement; import java.sq ...

  8. Jdbc执行存储过程报数据库事务无法执行的异常

    Jdbc执行存储过程报数据库事务无法执行的异常 环境: Eclipse+Jdk1.7+spring-jdbc-3.0.7+同版本的jdbctemplate+Sqlserver 2012 问题: 一个小 ...

  9. JDBC调用存储过程,进参出参

    今天做了一个数据表拷贝的功能,用到了存储过程,就写了一个java中用jdbc调用存储过程的代码,成功的实现了功能,晚上跑回家记录下 Connection conn = ConnectionUtil.g ...

  10. oracle学习笔记(二十三)——JDBC调用存储过程以及批量操作

    jdbc调用存储过程 使用并获得out模式的参数返回值 //存储过程为sum_sal(deptno department.deptno%type,sum in out number) Callable ...

随机推荐

  1. "码代码"微信号今日上线,为互联网同仁提供最前沿咨询

    "码代码"微信号今日上线 关注即有好礼相送 三月,春意浓浓的日子,三月,属于女人的日子,而今天...... “2014年天空成人放送大赏”于5日晚举办颁奖典礼,“年度最佳AV女优” ...

  2. H.264学习笔记2——帧内预测

    帧内预测:根据经过反量化和反变换(没有进行去块效应)之后的同一条带内的块进行预测. A.4x4亮度块预测: 用到的像素和预测方向如图: a~f是4x4块中要预测的像素值,A~Q是临块中解码后的参考值. ...

  3. QPushButton注册事件过滤器后按钮消失

    版权声明:本文为博主原创文章,转载需要注明出处. RT,代码如下: ui.btn_set->installEventFilter(this); bool MousrHoverTest::even ...

  4. Node.js——require加载规则

    判断require中的标识参数: 非路径的标识参数:也被称为是核心模块,已经被编译到二进制文件中 带有路径标识参数:自定义模块,一般都是相对定位 第三方模块:表现形式与核心模块一样,但是实际不一样,它 ...

  5. python的logging的简单使用

    用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么了,但是当我需要看大量的地方或者在一个文件中查看的时候,这时候print就不大方便了,所 ...

  6. E. Wrong Answer

    E. Wrong Answer time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  7. 第2节 hive基本操作:10、外部分区表综合练习

    外部分区表综合练习: 需求描述:现在有一个文件score.csv文件,存放在集群的这个目录下/export/servers/scoredatas/month=201806,这个文件每天都会生成,存放到 ...

  8. 梯度提升决策树(GBDT)与XGBoost、LightGBM

    今天是周末,之前给自己定了一个小目标:每周都要写一篇博客,不管是关于什么内容的都行,关键在于总结和思考,今天我选的主题是梯度提升树的一些方法,主要从这些方法的原理以及实现过程入手讲解这个问题. 本文按 ...

  9. js如何判断数组是Array类型

    在说明如何判断一个对象为数组类型前,我们先巩固下js的数据类型,js一共有六大数据类型:number.string.object.Boolean.null.undefined.var str=&quo ...

  10. Javascript中的For循环

    在开发的过程中,遍历是一个经常遇到的.而for循环则是Javascript工具箱里一个好用的,也常用的工具.每个人的习惯不同,for循环的写法也不尽相同. 1.不写声明变量的写法: for(var i ...