Java.sql.SQLSyntaxErrorException: ORA-01729: ожидаемое имя ссылки базы данных при использовании хранимой процедуры Java

Я создал хранимую процедуру 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.

мы не можем видеть сообщение «Здесь идет оставшийся код», проблема, вероятно, здесь, когда вы пытаетесь получить те же данные или вызвать что-то из базы данных.

OracleDev 04.01.2019 12:04

Вы не показали нам код, который на самом деле вызывает ошибку - включите всю процедуру Java, чтобы мы могли, по крайней мере, увидеть, что это за строка 25 и запрос, который вы выполняете в ней. Ошибка предполагает, что у вас есть запрос с ошибочным @, возможно, из-за неправильного построения строки запроса или неправильной настройки переменной, но, поскольку мы не видим ваш код, мы можем делать только смутные предположения.

Alex Poole 04.01.2019 12:04

@AlexPoole отредактировал код ..

Ravi Shankar 07.01.2019 10:52

@OracleDev отредактировал код ..

Ravi Shankar 07.01.2019 10:53
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
2 140
2

Ответы 2

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

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

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

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

Не думаю, что это правда. Если соединение не было успешным, вероятно, было сгенерировано исключение SQLException, поэтому оно не достигнет следующей строки? Кроме того, генерируемая ошибка исходит из БД, поэтому она должна быть подключена в тот момент, когда он выполняет запрос (который мы не видим ...)

Alex Poole 04.01.2019 12:12

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

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();

I am getting a "java.sql.SQLException: ORA-22922: nonexistent LOB value".

Изначально я тестировал за пределами БД, но увидел, что это более полно воспроизводит вашу настройку. Единственный способ, которым я до сих пор этого избегал, - это избегать неявного временного 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;
/

Хорошее объяснение! :) но теперь я получаю «java.sql.SQLException: ORA-22922: несуществующее значение LOB». Я пробовал использовать to_clob в вызове (выполнить GETSHEETROWS (14, to_clob ('{"name": "sheet" ........')), но безуспешно.

Ravi Shankar 07.01.2019 19:47

Ваш исходный тестовый вызов в любом случае выполнит неявное преобразование из строкового литерала varchar2 в CLOB. Это ошибка setClob, executeQuery или вашего тестового вызова?

Alex Poole 07.01.2019 19:52

он приходит во время тестового звонка

Ravi Shankar 07.01.2019 20:06

Похоже, это потому, что это временный LOB, и я думаю, что он выпускается стороной PL / SQL, в то время как сторона Java все еще пытается его использовать, что неудобно. Я смог избежать этого, только создав таблицу с этим значением, а затем используя это как часть вызова. Не совсем уверен, почему, но, надеюсь, ваши настоящие значения все равно будут взяты из таблицы.

Alex Poole 07.01.2019 21:51

Конечно, все это предполагает, что у вас есть законная причина бросить Java, чтобы сделать это в первую очередь ... * 8-)

Alex Poole 07.01.2019 21:59

могу ли я вместо создания новой таблицы: выбрать (данные json) в L_clob из двойного;

Ravi Shankar 11.01.2019 10:30

@RaviShankar - Я создал t только как место для хранения исходного CLOB, чтобы он был постоянным объектом, чтобы избежать этой ошибки. Это может потребоваться для автономной проверки вашей функции. Но откуда берутся настоящие данные JSON / CLOB, когда вы используете это по-настоящему? Из таблицы, которая уже существует?

Alex Poole 11.01.2019 10:35

Другие вопросы по теме