Я создал хранимую процедуру 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.
Вы не показали нам код, который на самом деле вызывает ошибку - включите всю процедуру Java, чтобы мы могли, по крайней мере, увидеть, что это за строка 25 и запрос, который вы выполняете в ней. Ошибка предполагает, что у вас есть запрос с ошибочным @, возможно, из-за неправильного построения строки запроса или неправильной настройки переменной, но, поскольку мы не видим ваш код, мы можем делать только смутные предположения.
@AlexPoole отредактировал код ..
@OracleDev отредактировал код ..




Не удалось установить соединение.
Сообщение «соединение успешно» будет распечатано во всех случаях. Даже если getConnection вернет null или ошибку, System.out.print все равно будет печатать «соединение успешно».
Возможно, вы захотите добавить оператор if или оператор try catch для проверки наличия соединения вместо добавления оператора System.out.print, который не проверяет наличие соединения и просто выводит сообщение «соединение успешно»
PS: проверьте свой URL-адрес и / или банки, которые вы используете.
Не думаю, что это правда. Если соединение не было успешным, вероятно, было сгенерировано исключение SQLException, поэтому оно не достигнет следующей строки? Кроме того, генерируемая ошибка исходит из БД, поэтому она должна быть подключена в тот момент, когда он выполняет запрос (который мы не видим ...)
Если вы добавите базовую отладочную печать вашего сгенерированного оператора, например:
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" ........')), но безуспешно.
Ваш исходный тестовый вызов в любом случае выполнит неявное преобразование из строкового литерала varchar2 в CLOB. Это ошибка setClob, executeQuery или вашего тестового вызова?
он приходит во время тестового звонка
Похоже, это потому, что это временный LOB, и я думаю, что он выпускается стороной PL / SQL, в то время как сторона Java все еще пытается его использовать, что неудобно. Я смог избежать этого, только создав таблицу с этим значением, а затем используя это как часть вызова. Не совсем уверен, почему, но, надеюсь, ваши настоящие значения все равно будут взяты из таблицы.
Конечно, все это предполагает, что у вас есть законная причина бросить Java, чтобы сделать это в первую очередь ... * 8-)
могу ли я вместо создания новой таблицы: выбрать (данные json) в L_clob из двойного;
@RaviShankar - Я создал t только как место для хранения исходного CLOB, чтобы он был постоянным объектом, чтобы избежать этой ошибки. Это может потребоваться для автономной проверки вашей функции. Но откуда берутся настоящие данные JSON / CLOB, когда вы используете это по-настоящему? Из таблицы, которая уже существует?
мы не можем видеть сообщение «Здесь идет оставшийся код», проблема, вероятно, здесь, когда вы пытаетесь получить те же данные или вызвать что-то из базы данных.