Oracle ORA-29536 on DDL-loading java source into the database

Oracle ORA-29536 on DDL-loading java source into the database

我正在考虑在 pl/sql 中包装一些 java 函数,但在加载 java 源代码时,我在 for 循环中的冒号字符上遇到了 ORA-29536。
我希望了解为什么数据库对此有困难,因为它似乎没有误解冒号并试图绑定,并希望获得关于前进道路的任何建议。
我想避免重构源代码以废除所有 for 循环,并希望尽可能避免使用 loadjava 工具。
数据库是12cR1,ojdk是1.6.0_71。

这是一个例子。
鉴于这两个琐碎的 hello-world-type 类:

public final class HelloWorld {
    public static String greet(final String userName) {
        return "Hello " + userName;
    }
}

并且:

import java.util.Arrays;
import java.util.List;

public final class LoopingTest {
    public static String greet(final String userName) {
        final List<String> emptyList = Arrays.asList(userName);
        for (final String string : emptyList) {
            System.out.println(string);
        }
        return "Hello " + userName;
    }
}

当我编译到数据库中时,第一个很好地注册了 JAVA SOURCEJAVA CLASS 对象(我在这个例子中使用动态 SQL 和一个 clob 因为最终目标将是 >32K 个字符,有足够的 @& 等来使原始脚本中的转义复杂化):

BEGIN
    EXECUTE IMMEDIATE
    '
        CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "HelloWorld" AS 
        public final class HelloWorld {
            public static String greet(final String userName) {
                return "Hello " + userName;
            }
        }
    ';
END;
/

PL/SQL procedure successfully completed.

但是第二个导入失败:

BEGIN
    EXECUTE IMMEDIATE
    '
        CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "HelloWorld" AS 
        import java.util.Arrays;
        import java.util.List;

        public final class LoopingTest {
            public static String greet(final String userName) {
                final List<String> emptyList = Arrays.asList(userName);
                for (final String string : emptyList) {
                    System.out.println(string);
                }
                return "Hello " + userName;
            }
        }
    ';
END;
/

ERROR at line 1:
ORA-29536: badly formed source: Encountered "final String string :" at line 1,
column 195.

我想知道我是否可以做任何更改来哄 oracle 加载它。
如果使用 loadjava 是唯一的导入方式,我可以接受,但如果可能的话,我更愿意一步加载 DDL。谢谢

Oracle 似乎对 Java 代码进行了一些奇怪的预处理,这些代码将 for-each 循环中的 final String string 标记为问题。该错误并非来自 Java 编译器 - 如您所料,因为这是有效的。我看不到有关此问题的任何信息,包括在 My Oracle Support 上。

正如@JonHeller 在编辑评论中指出的那样,它与字符串连接没有任何关系,但也与动态没有任何关系 SQL - 在 11gR2 中我仍然看到如果我直接从 SQL 提示符 运行 DDL,使用你的第二个代码块,同样的 ORA-29536 错误。

CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "LoopingTest" AS 
import java.util.Arrays;
import java.util.List;

public final class LoopingTest {
    public static String greet(final String userName) {
        final List<String> emptyList = Arrays.asList(userName);
        for (final String string : emptyList) {
            System.out.println(string);
        }
        return "Hello " + userName;
    }
}
/

Error report -
ORA-29536: badly formed source: Encountered "final String string :" at line 7, column 14.
Was expecting one of:
    "boolean" ...
...

作为解决方法,您只需删除 final 关键字:

CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "LoopingTest" AS 
import java.util.Arrays;
import java.util.List;

public final class LoopingTest {
    public static String greet(final String userName) {
        final List<String> emptyList = Arrays.asList(userName);
        // remove 'final' to avoid ORA-29536
        // for (final String string : emptyList) {
        for (String string : emptyList) {
            System.out.println(string);
        }
        return "Hello " + userName;
    }
}
/

Java source LoopingTest compiled

或者在您原来的 PL/SQL 代码中:

DECLARE
  V_SQL_TEXT CLOB := ' ' ||
                     'CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED "LoopingTest" AS ' ||
                     'import java.util.Arrays; ' ||
                     'import java.util.List; ' ||
                     ' ' ||
                     'public final class LoopingTest { ' ||
                     'public static String greet(final String userName){ ' ||
                     'final List<String> emptyList = Arrays.asList(userName); ' ||
                     -- remove 'final' to avoid ORA-29536
                     -- 'for (final String string : emptyList){ ' ||
                     'for (String string : emptyList){ ' ||
                     'System.out.println(string); ' ||
                     '} ' ||
                     'return "Hello " + userName; ' ||
                     '} ' ||
                     '} ';
BEGIN
  EXECUTE IMMEDIATE V_SQL_TEXT;
END;
/

PL/SQL procedure successfully completed.

您应该考虑向 Oracle 提出服务请求,看看他们是否可以解释 and/or 解决问题。