【问题标题】:Oracle ORA-29536 on DDL-loading java source into the databaseOracle ORA-29536 关于 DDL 将 java 源加载到数据库中
【发布时间】:2017-04-02 21:31:00
【问题描述】:

我正在考虑在 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 字符,其中足够@&amp; 等使原始脚本中的转义变得复杂):

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。谢谢

【问题讨论】:

  • 在 11gR2 (1.5.0_51) 中,它似乎不喜欢 final String,尽管完整的错误消息也没有按预期列出纯的 String,但它似乎可以编译为只是删除了 final 关键字。我现在无法在 12c 中测试,您也是这样吗?
  • 谢谢@AlexPoole 这很有趣。尽管删除任何 final 关键字让我感到难过,但这可能是一个可行的折衷方案。我离开我的机器几个小时了,但我会跟进 12c 是否认为它与 11g 相同。
  • @AlexPoole 果然,在 12c 中成功加载所需的唯一更改就是在循环中删除 final 修饰符。尽管我对final 造成的麻烦感到有些困惑,而且我很想知道为什么这里不支持final 的背景,但这清除了这个障碍。我会接受这是对近端原因的回答和可行的前进道路。感谢您的观看。
  • 我还没有弄清楚为什么需要这样做,或者能够找到任何与 MoS 相关的内容。

标签: java oracle plsql ddl


【解决方案1】:

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

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

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 提出服务请求,看看他们能否解释和/或解决问题。

【讨论】:

  • 谢谢亚历克斯。好建议;我会在 oracle 跟进。如果有什么有趣的事情我会在这里更新。
  • 这里只是一个后续。我接受了您的建议——SR 在 Oracle 并正在接受审查。当它进来时,我会更新解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-20
  • 2017-08-03
  • 1970-01-01
相关资源
最近更新 更多