详解Java的JDBC API的存储过程与SQL转义语法的使用

正如一个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()方法的参数。
  • OUT:其值是由它返回的SQL语句提供的参数。你从OUT参数的getXXX()方法检索值。
  • INOUT:同时提供输入和输出值的参数。绑定setXXX()方法的变量,并与getXXX()方法检索值。

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

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

String变量的SQL表示存储过程,使用参数占位符。

使用CallableStatement对象是使用PreparedStatement对象。必须将值绑定到所有的参数执行该语句之前,否则将收到一个SQLException。

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

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

一旦调用存储过程,用getXXX()方法的输出参数检索值。这种方法投射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();
}

PS:CallableStatement对象实例
下面是利用CallableStatement连同下列getEmpName()的MySQL存储过程的例子:

请确定已经在EMP数据库中创建该存储过程。可以使用MySQL查询浏览器来完成它。

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.java,编译并运行,如下所示:

//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/EMP";

  // Database credentials
  static final String USER = "username";
  static final String PASS = "password";

  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

现在编译上面的例子如下:

C:>javac JDBCExample.java

当运行JDBCExample,它会产生以下结果:

C:>java JDBCExample
Connecting to database...
Creating statement...
Executing stored procedure...
Emp Name with ID:102 is Zaid
Goodbye!

JDBC的SQL转义语法:
转义语法使能够使用通过使用标准的JDBC方法和属性,无法使用数据库的某些特性的灵活性。

一般的SQL转义语法格式如下:

{keyword 'parameters'}

这里有以下这些,会发现非常有用的,而这样做的JDBC编程的转义序列:

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点三十分29秒.

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

这是上述两种语法 'd' 和  't' 来表示时间戳结合语法。

escape 关键字:
该关键字标识LIKE子句中使用的转义字符。有用使用SQL通配符%,其中匹配零个或多个字符时。例如:

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

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

fn 关键字:
此关键字代表在DBMS中使用标量函数。例如,可以使用SQL length函数计算GE字符串的长度:

{fn length('Hello World')}

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

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

{call my_procedure(?)};

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

{? = call my_procedure(?)};

oj 关键字:
此关键字用来表示外部联接。其语法如下:

{oj outer-join}

外连接表={LEFT| RIGHT| FULL}外连接{表|外连接}的搜索条件。例如:

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

相关推荐

  • Java的基础语法学习笔记

    零.Java的关键字 用于类和接口的声明:class, extends, implements, interface 包引入和包声明:import, package 数据类型:boolean, byte, char, short, int, long, float, double 某些数据类型的可选值:false, true, null 流程控制:default, return, if, else, for, switch, case, do, while, break, continue, 异

  • java 学习笔记(入门篇)_java的基础语法

    前言 学习完了第一个java程序,之后就来系统的学习java.先从基础语法开始,这个语法你也可以理解为英语或是汉语里面的语法,只不过大家各有各的特点和区别.学习编程其实也是一个编程语言的学习过程.我们在学习英语的时候都说,要想学习好英语一定要动口说,那么在学习编程的时候你一定要动手写.编程无非就是一个写代码的过程,首要就是你心中要有基础,没有基础怎么去写呢,就像一篇好文章,没有好文笔是写不出来的.好文笔不仅靠积累,更要靠创造,编程亦是如此.java是一个面向对象的语言,在写代码的过程中,接触最多

  • Java入门基础之Java的基本语法与Java所支持的数据类型

    Java 应用程序可以被定义为对象的集合,这些对象通过调用各自的方法来进行通信.下面让我们具体看一看类,对象,方法,实体变量是什么含义. 对象:对象具有状态和行为.例如:狗有它的状态-颜色,名字,品种,同时也有行为-摇尾巴,汪汪叫,吃东西.对象时类的一个实例. 类:类可以被定义为描述对象所支持的类型的行为和状态的模板或蓝图. 方法:方法是一种基本的行为.类中可以包含很多方法.在方法中,可以编写逻辑,操纵数据,执行动作. 实体变量:每个对象都有它的特殊的实体变量的集合,一个对象的状态是由那些实体变

  • 详解Java正则表达式语法

    分享的Java正则表达式语法和示例如下 1.匹配验证-验证Email是否正确 public static void main(String[] args) { // 要验证的字符串 String str = "service@xsoftlab.net"; // 邮箱验证规则 String regEx = "[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\\.){1,3}[a-zA-z\\-]{1,}"; // 编译正则表达式

  • Java语法基础之for语句练习

    控制语句--for练习语句的嵌套应用累加求和,计数器循环嵌套一.语句的嵌套应用语句嵌套形式.其实就是语句中还有语句.形式多种多样,没有固定的格式和套路.1.打印偶数for(int x=1;x<=10;x++){  if(x%2==1)continue; System.out.prinln("x="+x);}二.累加求和,计数器1.获取1~10的和,并打印.思路://1,定义变量用于存储不断变化的和.       int sum = 0;       //2,定义变量,记录住不断变

  • java与c#的语法区别详细介绍

    由C#转入Java一段时间了,总结下个人认为的Java同C#语法之间的不同之处,有不同意见之处还望各位海涵 刚学Java时觉得语法同C#大致是相同的(应该说C#同Java大致相同,毕竟人家微软的C#是有意模仿Java的语法习惯的) 比尔.盖茨曾经说过:"Java是最卓越的程序设计语言" 言归正传,下面探讨Java同C#的语法不同之处... 1,命名空间与包 C#为了把实现相似功能的类组织在一起,引入了命名空间的概念(namespace) Java中与此对应的东西叫做包(package)

  • Java语法基础之函数的使用说明

    函数四个方面:函数的定义函数的特点函数的应用函数的重载 一.函数的定义及特点1) 什么是函数?函数就是定义在类中的具有特定功能的一段独立小程序,函数也称为方法2)Java中函数的格式:修饰符 返回值类型函数名(参数类型 形式参数1,参数类型 形式参数2,..){  执行语句; return 返回值:}返回值类型:函数运行后的结果的数据类型参数类型:是形式参数的数据类型形式参数:是一个变量,用于存储调用函数时传递给函数的实际参数实际参数:传递给形式参数的具体数值return:用于结束函数返回值:该

  • 详解Java的JDBC API的存储过程与SQL转义语法的使用

    正如一个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_FIRS

  • 详解Java的JDBC API中事务的提交和回滚

    如果JDBC连接是在自动提交模式下,它在默认情况下,那么每个SQL语句都是在其完成时提交到数据库. 这可能是对简单的应用程序,但有三个原因,你可能想关闭自动提交和管理自己的事务: 为了提高性能 为了保持业务流程的完整性 使用分布式事务 若要控制事务,以及何时更改应用到数据库.它把单个SQL语句或一组SQL语句作为一个逻辑单元,而且如果任何语句失败,整个事务失败. 若要启用,而不是JDBC驱动程序默认使用auto-commit模式手动事务支持,使用Connection对象的的setAutoComm

  • 详解Java数据库连接JDBC基础知识(操作数据库:增删改查)

    一.JDBC简介 JDBC是连接java应用程序和数据库之间的桥梁. 什么是JDBC? Java语言访问数据库的一种规范,是一套API. JDBC (Java Database Connectivity) API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库.比如建立数据库连接.执行SQL语句进行数据的存取操作. JDBC代表Java数据库连接. JDBC库中所包含的API任务通常与数据库使用: 连接到数据库 创

  • 详解Java使用JDBC连接MySQL数据库

    一:什么是数据库,为什么要有数据库? 数据,数据库,数据库管理系统和数据库系统是与数据库技术密切相关的四个基本概念. 数据库相信大家都耳熟能详了,其实数据库顾名思义就是存放数据的仓库,只不过这个仓库是在计算机存储设备上,而且数据是按一定的格式存放的~ 可能有朋友就要打断我施法了,停停停,我们Java程序猿在IDEA里面和控制台你侬我侬,没有对象new个对象存储在内存JVM的堆上就行了,学数据库干啥啊? 这时候我们就需要了解到:内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运

  • 详解JAVA生成将图片存入数据库的sql语句实现方法

    详解JAVA生成将图片存入数据库的sql语句实现方法 实现代码: 注释很清楚,不在重述~ public class Image2Hex { public static void main(String[] args) { try{ //存放图片的文件夹 File list = new File("d:/qmx"); File[] lists = list.listFiles(); String name; //生成的语句存放文件 PrintWriter pw = new PrintWr

  • 详解Java的JDBC中Statement与PreparedStatement对象

    一旦获得一个连接,我们可以与数据库进行交互.在JDBC Statement, CallableStatement 和 PreparedStatement 接口定义的方法和属性,使可以发送SQL或PL/SQL命令和从数据库接收数据. 它们还定义方法,帮助Java和数据库使用SQL数据类型之间转换数据的差异. 下表提供了每个接口的用途概要,了解决定使用哪个接口 Statement 对象: 创建Statement对象 在可以使用Statement对象执行SQL语句,需要使用Connection对象的c

  • 详解java调用存储过程并封装成map

    详解java调用存储过程并封装成map 本文代码中注释写的比较清楚不在单独说明,希望能帮助到大家, 实例代码: public List<Map<String , Object>> doCallProcedure(String procedureString,String[] parameters) throws PersistentDataOperationException { if (!isReady ()) { throw new PersistentDataOperatio

  • 详解Java关于JDK中时间日期的API

    目录 JDK 8中关于日期和时间的API测试 JDK 8 之前日期和时间的API测试 //1.System类中的currentTimeMillis() public void test1(){ long time = System.currentTimeMillis(); //返回当前时间与1970年1月1日0时0分0秒之间以毫秒为时间为单位的时间差. //称为时间戳 System.out.println(time);//1628416744054 } /* java.util.Date类 |-

  • 详解Java事件编程的使用

    Java事件编程 当前在线网店很多,很涉及商品管理和销售的问题,比如: 一,在商品库存管理的商品增加时,我们主要业务时编辑保持商品信息, 同时因商品增加而附带有一些"非主要业务",如: 1,应商品的库存数量等更新, 2,热销产品的推广处理等 二,在商品产生订单时,我们的主要业务(对买家而言)是建立订单业务, 同时因产生订单而附带有一些不是买家关心的"非主要业务",如: 1,库存和已售数量的更新 2,发货的准备处理事宜 3,物流的处理事宜 非主要业务我们可以让程序使用

  • 详解Java子线程异常时主线程事务如何回滚

    一.提出问题 最近有一位朋友问了我这样一个问题,问题的截图如下: 这个问题问的相对比较笼统,我来稍微详细的描述下:主线程向线程池提交了一个任务,如果执行这个任务过程中发生了异常,如何让主线程捕获到该异常并且进行事务的回滚. 二.主线程与子线程 先来看看基础,下图体现了两种线程的运行方式, 左侧的图,体现了主线程启动一个子线程之后,二者互不干扰独立运行,生死有命,从此你我是路人! 右侧的图,体现了主线程启动一个子线程之后继续执行主线程程序逻辑,在某一节点通过阻塞的方式来获取子线程的执行结果. 对于

随机推荐