Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 12.0.1 » SQL Anywhere 服务器 - 编程 » SQL Anywhere 外部环境支持

 

Java 外部环境

SQL Anywhere 支持 Java 存储过程和函数。Java 的存储过程或函数的行为与 SQL 存储过程或函数的行为基本相同,只是过程或函数的代码以 Java 编写并且在数据库服务器外(即在 Java VM 环境内)执行过程或函数。应该注意的是,每个数据库对应于一个 Java VM 实例,而不是每个连接对应于一个实例。Java 存储过程可以返回结果集。

在数据库支持中使用 Java 有几个前提条件:

  1. 必须在数据库服务器计算机上安装 Java 运行时环境的副本。

  2. SQL Anywhere 数据库服务器必须能够找到 Java 可执行文件 (Java VM)。

要在数据库中使用 Java,需确保数据库服务器能够找到并启动 Java 可执行文件。通过执行以下语句可验证这一点:

START EXTERNAL ENVIRONMENT JAVA;

如果数据库服务器未能启动 Java,问题的原因可能是数据库服务器不能找到 Java 可执行文件。这种情况下,应执行 ALTER EXTERNAL ENVIRONMENT 语句来显式设置 Java 可执行文件的位置。务必要包含可执行文件名。

ALTER EXTERNAL ENVIRONMENT JAVA
  LOCATION 'java-path';

例如:

ALTER EXTERNAL ENVIRONMENT JAVA
  LOCATION 'c:\\jdk1.6.0\\jre\\bin\\java.exe';

可以执行以下 SQL 查询来查询数据库服务器将使用的 Java VM 的位置:

SELECT db_property('JAVAVM');

请注意,除了验证数据库服务器可以启动 Java VM 外,START EXTERNAL ENVIRONMENT JAVA 语句并不是必需的。通常,进行 Java 存储过程或函数的调用会自动启动 Java VM。

类似地,停止 Java 的实例时 STOP EXTERNAL ENVIRONMENT JAVA 语句也不是必需的,因为在数据库的所有连接终止时该实例会自动消失。然而,如果要彻底离开 Java 并且想要释放一些资源,STOP EXTERNAL ENVIRONMENT JAVA 语句则可以减少 Java VM 的使用量。

验证了数据库服务器可以启动 Java VM 可执行文件后,接下来要做的事就是在数据库中安装所需的 Java 类代码。使用 INSTALL JAVA 语句即可完成。例如,可以执行以下语句来将 Java 类从文件安装到数据库。

INSTALL JAVA 
NEW 
FROM FILE 'java-class-file';

也可以将 Java JAR 文件安装到数据库中。

INSTALL JAVA 
NEW
JAR 'jar-name'
FROM FILE 'jar-file';

可以从变量安装 Java 类,如下所示:

CREATE VARIABLE JavaClass LONG VARCHAR;
SET JavaClass = xp_read_file('java-class-file')
INSTALL JAVA 
NEW
FROM JavaClass;

可以从变量安装 Java JAR 文件,如下所示:

CREATE VARIABLE JavaJar LONG VARCHAR;
SET JavaJar = xp_read_file('jar-file')
INSTALL JAVA 
NEW
JAR 'jar-name'
FROM JavaJar;

要从数据库中删除 Java 类,请使用 REMOVE JAVA 语句,如下所示:

REMOVE JAVA CLASS java-class

要从数据库中删除 Java JAR,请使用 REMOVE JAVA 语句,如下所示:

REMOVE JAVA JAR 'jar-name'

要修改现有 Java 类,可以使用 INSTALL JAVA 语句的 UPDATE 子句,如下所示:

INSTALL JAVA 
UPDATE
FROM FILE 'java-class-file'

也可以在数据库中更新现有 Java JAR 文件。

INSTALL JAVA 
UPDATE
JAR 'jar-name'
FROM FILE 'jar-file';

可以从变量更新 Java 类,如下所示:

CREATE VARIABLE JavaClass LONG VARCHAR;
SET JavaClass = xp_read_file('java-class-file')
INSTALL JAVA 
UPDATE
FROM JavaClass;

可以从变量更新 Java JAR 文件,如下所示:

CREATE VARIABLE JavaJar LONG VARCHAR;
SET JavaJar = xp_read_file('jar-file')
INSTALL JAVA 
UPDATE
FROM JavaJar;

Java 类安装在数据库中后,接下来可以创建存储过程和函数,以与 Java 方法连接。EXTERNAL NAME 字符串包含了调用 Java 方法以及返回 OUT 参数和返回值所需的信息。EXTERNAL NAME 子句的 LANGUAGE 属性必须指定 JAVA。EXTERNAL NAME 子句的格式是:

EXTERNAL NAME 'java-call' LANGUAGE JAVA
java-call :
[package-name.]class-name.method-name method-signature
method-signature : 
( [ field-descriptor, ... ] ) return-descriptor
field-descriptorreturn-descriptorZ | B | S | I | J | F | D | C | V | [descriptor | Lclass-name;

Java 方法签名是参数类型和返回值类型的压缩字符表示形式。如果参数的数目比方法签名中指出的数目少,则差值必须等于 DYNAMIC RESULT SETS 中指定的个数,并且方法签名中超出过程参数列表中参数的每个参数必须具有方法签名 [Ljava/sql/ResultSet;

field-descriptorreturn-descriptor 具有以下含义:

字段类型 Java 数据类型
B byte
C char
D double
F float
I int
J long
L class-name; class-name 的实例。类名必须是完全限定的,而且名称中的任何点都必须替换为 /。例如 java/lang/String
S short
V void
Z Boolean
[ 数组的每个维度都使用一个

例如:

double some_method(
  boolean a,
  int b,
  java.math.BigDecimal c,
  byte [][] d,
  java.sql.ResultSet[] rs ) {
}

可以有以下签名:

'(ZILjava/math/BigDecimal;[[B[Ljava/sql/ResultSet;)D'

以下过程创建 Java 方法的接口。Java 方法不返回任何值 (V)。

CREATE PROCEDURE insertfix() 
EXTERNAL NAME 'JDBCExample.InsertFixed()V' 
LANGUAGE JAVA;

以下过程创建具有字符串 ([Ljava/lang/String;) 输入参数的 Java 方法的接口。Java 方法不返回任何值 (V)。

CREATE PROCEDURE InvoiceMain( IN arg1 CHAR(50) )
EXTERNAL NAME 'Invoice.main([Ljava/lang/String;)V'
LANGUAGE JAVA;

以下过程创建 Java 方法 Invoice.init(采用一个字符串参数 (Ljava/lang/String;)、一个双精度参数 (D)、另一个字符串参数 (Ljava/lang/String;) 和另一个双精度参数 (D))的接口,并且不返回任何值 (V)。

CREATE PROCEDURE init( IN arg1 CHAR(50),
                       IN arg2 DOUBLE, 
                       IN arg3 CHAR(50), 
                       IN arg4 DOUBLE) 
EXTERNAL NAME 'Invoice.init(Ljava/lang/String;DLjava/lang/String;D)V'
LANGUAGE JAVA

下面的 Java 示例包含函数 main,此函数以字符串作为参数并将其写入到数据库服务器的消息窗口:它还包含函数 whoAreYou,此函数会返回一个 Java 字符串。



import java.io.*;

public class Hello
{
    public static void main( String[] args )
    {
        System.out.print( "Hello" );
               for ( int i = 0; i  < args.length; i++ )
                   System.out.print( " " + args[i] );
        System.out.println();
    }
    public static String whoAreYou()
    {
        return( "I am SQL Anywhere." );
    }
}

以上 Java 代码位于 Hello.java 文件中,并使用 Java 编译器进行编译。所生成的类文件将装载到数据库中,如下所示。

INSTALL JAVA 
NEW 
FROM FILE 'Hello.class';

使用 Interactive SQL,用于在 Hello 类中连接方法 main 的存储过程将按如下方式创建:

CREATE PROCEDURE HelloDemo( IN name LONG VARCHAR ) 
EXTERNAL NAME 'Hello.main([Ljava/lang/String;)V'
LANGUAGE JAVA;

请注意,main 的参数以 java.lang.String 的数组形式进行描述。使用 Interactive SQL,通过执行以下 SQL 语句来测试该接口。

CALL HelloDemo('SQL Anywhere');

如果检查数据库服务器消息窗口,将会找到此处写入的消息。所有到 System.out 的输出将重定向到服务器消息窗口。

使用 Interactive SQL,可如下所示创建将会在 Hello 类中作为 whoAreYou 方法接口的函数:

CREATE FUNCTION WhoAreYou()
RETURNS LONG VARCHAR
EXTERNAL NAME 'Hello.whoAreYou(V)Ljava/lang/String;'
LANGUAGE JAVA;

请注意,函数 whoAreYou 通过返回 java.lang.String 进行描述。使用 Interactive SQL,可通过执行以下 SQL 语句来测试该接口。

SELECT WhoAreYou();

您可以在 Interactive SQL [结果] 窗口中看到响应。

Java 外部环境没有启动,即应用程序调用 Java 时得到 "找不到主线程" 错误,要排查此问题,DBA 应检查以下内容:

  • 如果 Java VM 与数据库服务器位不相同,请确保在数据库服务器计算机上安装了与 VM 位相同的客户端库。

  • 确保 sajdbc.jardbjdbc12/libdbjdbc12 共享对象来自相同内部版本的软件。

  • 如果数据库服务器计算机上有多个 sajdbc.jar,确保它们都同步到了相同版本的软件。

  • 如果数据库服务器计算机忙,由于超时可能会报告该错误。

 另请参见