java.sql.SQLSyntaxErrorException: ORA-01729: ожидается имя ссылки на базу данных при использовании хранимой процедуры Java - PullRequest
0 голосов
/ 04 января 2019

Я создал хранимую процедуру Java в Oracle, используя запрос:

CREATE OR REPLACE PROCEDURE GETSHEETROWS(I_file_id number, I_sheetNode clob,template_key  varchar2 ,wksht_key  varchar2 ,wksht_name varchar2 )
 AS LANGUAGE JAVA
 NAME 'SheetRowsJson.getSheetRows(int, java.sql.Clob, java.lang.String, java.lang.String, java.lang.String)';
 /

Ниже приведен мой код Java. (Входные данные I_sheetnode относятся к типу json. Поскольку в plsql нет типа данных Jsontype, я использовал clob там и так, я использовал то же самое здесь)

public static void getSheetRows( int I_file_id, Clob I_sheetNode, String 
template_key, String wksht_key,String wksht_name ) {
    try{
            String url = "jdbc:oracle:thin:@xxxxx:port/yyyyy";
            Connection  conn = DriverManager.getConnection(url,"username","password");
            System.out.println("-------------------Connection Successful--------------------------------");
            String sheetRows = "select X.Node,X.rn from json_table (("+ I_sheetNode.toString() +"),'$.table_row[*]' COLUMNS(rn for ordinality,Node varchar2(4000) FORMAT JSON PATH '$')) X";
            PreparedStatement ps=conn.prepareStatement(sheetRows);
            ResultSet rs = ps.executeQuery();
/* Remaining code goes here */

Когда я пытаюсь запустить такую ​​процедуру,

set serveroutput on;
call dbms_java.set_output(50);
execute GETSHEETROWS(14,'{"name":"sheet","table_row":[{"value":"1","item":"11111","id":"2","value":"1","action":"NEW"},{"value":"2","item":"22222","id":"3","value":"4","action":"NEW"}]}','TEMPLATE','SHEET','Sheet1');
/

Я получаю следующий вывод:

Call completed.

-------------------Connection Successful--------------------------------
java.sql.SQLSyntaxErrorException: ORA-01729: database link name expected

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:399)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1059)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:522)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:257)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:587)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:225)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:53)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:774)
    at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java)
    at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java)
    at SheetRowsJson.getSheetRows(SheetRowsJson.java:25)


PL/SQL procedure successfully completed.

Я не могу выяснить причину этого. Поскольку печатается «Соединение установлено», действительно ли оно установлено? или нет? Если нет, то почему?

Примечание. Я уже загрузил класс Java с помощью утилиты loadjava.

Ответы [ 2 ]

0 голосов
/ 07 января 2019

Если вы добавите базовый отладочный отпечаток вашего сгенерированного оператора, например ::

System.out.println(sheetRows);

вы увидите что-то вроде:

select X.Node,X.rn from json_table ((oracle.sql.CLOB@77556fd),'$.table_row[*]' COLUMNS(rn for ordinality,Node varchar2(4000) FORMAT JSON PATH '$')) X

Метод toString() показывает идентификатор объекта, а не содержимое строки. И @ в этом идентификаторе вызывает ошибку, которую вы видите (как 77556fd или любое другое значение, которое вы видите, не является допустимым идентификатором объекта).

Вы можете встроить фактическое переданное строковое значение, но вам придется заключить его в одинарные кавычки, и вы будете ограничены размером строкового литерала в вашей БД (4 или 32 КБ, в зависимости от версии). и настройки), что делает использование CLOB в первую очередь бессмысленным; и вы все равно должны использовать переменные связывания, что-то вроде:

sheetRows = "select X.Node,X.rn from json_table (?,'$.table_row[*]' COLUMNS(rn for ordinality,Node varchar2(4000) FORMAT JSON PATH '$')) X";
PreparedStatement ps=conn.prepareStatement(sheetRows);
ps.setClob(1, I_sheetNode);
ResultSet rs= ps.executeQuery();

Я получаю "исключение java.sql.SQLException: ORA-22922: несуществующее значение большого объекта".

Первоначально я проводил тестирование вне БД, но видел, что это повторяет ваши настройки более полно. Единственный способ, которым я пока избегал этого, - это избежать неявного временного CLOB:

create table t (c) as (
  select to_clob('{"name":"sheet","table_row":[{"value":"1","item":"11111","id":"2","value":"1","action":"NEW"},{"value":"2","item":"22222","id":"3","value":"4","action":"NEW"}]}') from dual
);

declare
  l_clob clob;
begin
  select c into l_clob from t;
  getsheetrows(14, l_clob, 'TEMPLATE', 'SHEET', 'Sheet1');
end;
/
0 голосов
/ 04 января 2019

Соединение не установлено.

Сообщение « соединение успешно » будет напечатано во всех случаях. Даже если getConnection возвращает ноль или ошибку, System.out.print все равно выдает « соединение успешно ».

Возможно, вы захотите добавить оператор if или оператор try catch для проверки существования соединения вместо добавления оператора System.out.print, который не проверяет наличие соединения и просто печатает "соединение успешный "

PS: проверьте ваш URL и / или банки, которые вы используете.

...