1 Java存储过程
这篇文章是关于Java DB中的Java存储过程的。
Java DB是基于Java编程语言和SQL的关系数据库管理系统。 这是Apache软件基金会的开源Derby项目的Oracle版本。 Java SE 7 SDK中包含Java DB。
在数据库内调用的Java代码是一个存储过程(或多个过程)。 Java存储过程是数据库端JDBC(Java数据库连接)例程。
过程代码以Java类方法定义,并存储在数据库中。 这是使用SQL执行的。 该过程代码可以带有或不带有任何与数据库相关的代码。
其他数据库端(或服务器端)程序是触发器和表函数。
1.1 Java过程类型
根据在其中调用存储的事务,存储过程有两种类型:嵌套连接和非嵌套连接。
嵌套连接
这种过程使用与调用它的SQL语句相同的事务。 该过程代码使用与父SQL相同的连接,并使用连接URL语法jdbc:default:connection
。 以下是获得连接的示例代码位:
Connection c = DriverManager.getConnection("jdbc:default:connection");
请注意,此类型不支持连接URL属性。
示例代码位于: 2.1创建 。
非嵌套连接
这种类型的过程使用新的数据库连接。 该过程是在与调用SQL不同的事务中执行的。
存储过程代码也可以连接到其他数据库。
以下位置的示例代码: 3.1使用非嵌套连接 。
1.2过程中的SQL异常
过程中的SQL异常可以在过程代码中捕获和处理,或在调用程序中传播(捕获)。
2创建和使用Java存储过程
这描述了在Java DB数据库中创建Java存储过程以及在SQL和Java代码中以交互方式使用它的过程。 使用Java编程语言创建存储过程代码。 该过程是带有签名的public static void procedureMethod
方法中的Java代码。 创建存储过程并将其作为数据库对象存储在Java DB数据库中。
使用SQL命令或使用JDBC API从Java程序调用(或调用)该过程。
2.1建立
创建一个Java方法,对其进行编译,然后将该过程存储在数据库中。
2.1.1创建Java方法
以下是示例方法。
public static void testProc(int iParam1, String iParam2, int [] oParam)throws SQLException {String connectionURL = "jdbc:default:connection";Connection conn = DriverManager.getConnection(connectionURL);String DML = "UPDATE TEST_TABLE SET NAME = ? WHERE ID = ?";PreparedStatement pstmnt = conn.prepareStatement(DML);pstmnt.setString(1, iParam2);pstmnt.setInt(2, iParam1);int updateRowcount = pstmnt.executeUpdate();oParam [0] = updateRowcount;
} // testProc()
该代码在Java类(例如JavaStoredProcs.java
)中创建并进行编译。 一个类中可以创建任意数量的过程方法。
在示例代码中:
- 程序方法具有三个参数。 前两个参数(iParam1和iParam2)分别为IN,第三个为OUT参数模式。 注意,OUT参数指定为数组。 每个OUT和INOUT参数都需要在过程方法中指定为数组,并且仅将数组的第一个元素用作过程参数变量(即映射)。
- 该过程使用嵌套连接。
- 抛出的任何SQL异常都可以在调用程序或过程方法中进行处理。 在这种情况下,异常将在调用代码中处理。
2.1.2在数据库中创建过程
该过程是使用CREATE PROCEDURE语句在数据库中创建的。 该命令使用ij
交互式运行,或者使用JDBC API的java.sql.Statement
接口从Java程序运行。
命令语法和详细信息如下:
CREATE PROCEDURE procedure-Name(ProcedureParameters)ProcedureElements
procedure-Name
:是存储在数据库中的过程名称; 如果未指定,则在默认架构中创建。
ProcedureParameters
:指定参数模式(IN,INOUT或OUT),可选名称和数据类型。 数据类型是数据库数据类型。 Java DB在过程中不支持长列类型(例如Long Varchar,BLOB等)。 参数是可选的。
ProcedureElements:
此元素必须包含以下三个元素,并且可以具有其他可选元素。
- 语言JAVA。 这是唯一的值。
- 参数样式JAVA。 这是唯一的值。
- 外部名称。 这指定了执行过程时要调用的Java方法,并采用
ClassName.methodName Optional, procedure elements
形式,ClassName.methodName Optional, procedure elements
: - 动态结果集整数
- 确定性
- 外部安全
- 修改SQL数据(默认值),包含SQL,读取SQL数据,不使用SQL(无数据库相关代码的过程)
2.1.2.1使用ij
交互式地在数据库中创建过程
ij
是Java DB附带的命令行工具。 ij
是一个JDBC工具,用于在Java DB数据库上运行交互式查询。
ij> CONNECT 'jdbc:derby:testDB';
ij> CREATE PROCEDURE PROC_NAME(IN id1 INTEGER, IN name2 VARCHAR(50), OUT count3 INTEGER) LANGUAGE JAVA EXTERNAL NAME 'JavaStoredProcs.testProc' PARAMETER STYLE JAVA;
在示例中,过程PROC_NAME
在testDB
数据库中创建。 先前创建的Java方法 ( 2.1.1创建Java方法 )被指定为EXTERNAL NAME。
要列出数据库中的过程,请使用命令SHOW PROCEDURES。
2.2.2更改或删除过程
要更改过程,请从数据库中删除该过程,然后再次创建。
使用ij
删除过程的示例:
ij> DROP PROCEDURE procedureName;
2.2使用(调用)
使用SQL CALL命令以交互方式运行过程,或者使用JDBC API从客户端程序以交互方式运行过程。
CALL SQL命令仅支持IN参数。 JDBC API的CallableStatement
接口用于调用带有IN,INOUT或OUT参数的过程。
2.2.1 CALL SQL语句
CALL语句用于调用过程。 这不会返回值。 使用CALL调用时,仅支持带有IN参数的过程。
以下示例显示了从ij运行的CALL命令,以调用过程MyProc. MyProc
MyProc. MyProc
是数据库中使用CREATE PROCEDURE定义的过程的名称。
ij> CALL MyProc();
2.2.2从Java程序调用过程
此示例代码调用了先前创建的过程(PROC_NAME)(2.1创建)。
该代码使用JDBC API的CallableStatement
接口(有关更多详细信息,请参见2.2.3关于CallableStatement的说明 )。 在此示例方法的末尾,将设置过程的输入参数,并输出out参数值。 请注意,此Java类与创建过程的类不同。
private static void runStoredProc(Connection conn)throws SQLException {int iParam1 = 1;String iParam2 = "updated name data";String proc = "{call PROC_NAME(?, ?, ?)}";CallableStatement cs = conn.prepareCall(proc);cs.setInt(1, iParam1);cs.setString(2, iParam2);cs.registerOutParameter(3, java.sql.Types.INTEGER);cs.executeUpdate();String oParam = cs.getInt(3);System.out.println("Updated row count from the proc: " + oParam);
} // runStoredProc()
2.2.3关于CallableStatement的说明
Java JDBC API的CallableStatement
接口扩展了PreparedStatement
并在java.sql
包中定义。 这用于执行SQL存储过程。
该API提供了一种存储过程SQL转义语法,该语法允许所有RDBMS以标准方式调用过程。 语法的一种形式包含结果参数,另一种形式不包含结果参数。 如果使用,则结果参数必须注册为OUT参数。 其他参数(arg1,arg2,…)可用于输入,输出或两者都使用。
以下是语法(分别具有返回值和不具有返回值):
{? = call <procedure-name> [(arg1, arg2, ...)]}
{call <procedure-name> [(arg1, arg2, ...)]}
使用从PreparedStatement
继承的setter方法设置IN参数值。 在使用registerOutParameter()执行存储过程之前,必须先注册所有OUT参数的类型。 它们的值在执行后通过getXxx(int parameterIndex / StringparameterName)方法(getBoolean(),getArray()等)检索。
参数模式
参数属性IN(默认),OUT和INOUT是参数模式。
调用存储过程
String procName = "{call STORED_PRODURE_NAME(}";
CallableStatement cs = conn.prepareCall(procName);
ResultSet rs = cs.executeQuery();
要调用存储过程,请使用execute(),executeQuery()或executeUpdate()方法,具体取决于过程返回的ResultSet
对象数。 如果不确定该过程返回多少ResultSet
对象,请使用execute()方法。
cs = conn.prepareCall("{call INCR_PRICE(?, ?)}");
cs.setString(1, itemNameArg); // (1)
cs.setFloat(2, newPriceArg); // (2a)
cs.registerOutParameter(2, Types.NUMERIC); // (2b)
cs.execute();
float newPrice = cs.getFloat(2); // (2c)
第一参数1是IN参数。
第二个参数具有参数模式INOUT。 IN值是通过调用setter方法2a指定的,并使用registerOutParameter()方法2b注册OUT类型的。 通过吸气剂方法2c检索输出值。
3个例子
有两个示例:第一个显示创建和使用非嵌套类型过程的代码,第二个是Java DB预定义过程的示例用法。
3.1使用非嵌套连接
在此示例中,Java过程访问的数据库和连接与调用程序中使用的数据库和连接不同。 该过程返回OUT整数参数值。
- 创建并编译过程代码。
public static void testProc4(int [] retval)throws SQLException {String connectionURL = "jdbc:derby:testDB2";Connection conn = DriverManager.getConnection(connectionURL);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM ID_TABLE");int nextid = 0;while(rs.next()) {nextid = rs.getInt("ID");}retval[0] = nextid;conn.close(); // alternative: shutdown the database. } // testProc4()
- 在数据库中创建过程。
CREATE PROCEDURE PROC_NAME_4(OUT paramname INTEGER)LANGUAGE JAVAEXTERNAL NAME 'JavaStoredProcs.testProc4'PARAMETER STYLE JAVAREADS SQL DATA;
过程元素READS SQL DATA指定SQL in过程方法只能使用SELECT语句。
- 调用客户端程序中的过程。
private static void runStoredProc4(Connection conn)throws SQLException {String proc = "{call PROC_NAME_4(?)}";CallableStatement cs = conn.prepareCall(proc);cs.registerOutParameter(1, java.sql.Types.INTEGER);cs.execute();int oParamData = cs.getInt(1); // proc output value } // runStoredProc4()
3.2 Java DB内置系统过程
SYSCS_UTIL.SYSCS_BACKUP_DATABASE是预定义的且特定于Java DB的系统过程。 这会将数据库备份到指定目录。 语法为SYSCS_BACKUP_DATABASE(IN backupDirPath VARCHAR)。 该过程不返回值。
以下示例SQL命令调用该过程:
CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE('c:/backupdir');
注意:在http://www.javaquizplayer.com/blogposts/blogpost4.html上,标题为“ 备份Java DB数据库 ”的博客文章中提供了详细的Java代码示例。
4笔记
4.1与客户端代码相比,过程的某些优势
- 该例程允许将代码一次存储在数据库服务器上,并且可以从多个应用程序进行访问。 而且,与SQL相比,代码可能很复杂。
- 该代码在服务器上执行,因此减少了客户端-服务器应用程序中的网络流量。 这样可以提高应用程序的性能。
4.2其他RDBMS
Oracle的10g和HyperSQL数据库(HSQLDB)是其他一些支持Java存储过程的数据库。
5参考
- Apache Derby>文档(10.8手册)
- Java SE 7 API> java.sql程序包
翻译自: https://www.javacodegeeks.com/2013/09/java-stored-procedures-in-java-db.html