Хранимая функция Oracle Java - несогласованный тип данных для CLOB

У меня есть столбец CLOB, в котором хранится код html. Чтобы разобрать его, я написал сохраненную функцию Java -

CREATE or replace FUNCTION parse_html(value in CLOB) 
  RETURN CLOB  
   AS LANGUAGE JAVA NAME 'MyClass.parse(java.lang.String) return java.lang.String';

и добавил соответствующий класс Java.

Когда я вызываю эту функцию parse_html(clob_col_name) -

SELECT PARSE_HTML(m.clob_col_name) 
  FROM my_table m
  where length(m.clob_col_name) > 4000;

У меня следующая ошибка -

ORA-00932: несогласованные типы данных: ожидалось значение в позиции аргумента 1, которое может быть преобразовано в Java. Java.lang.String получил Oracle CLOB 00932. 00000 - «несовместимые типы данных: ожидаемый% s получил% s»

Обновление 1

Как я упоминал ранее, мне нужно проанализировать данные html с помощью Jsoup. jsoup.parse ожидает String в качестве аргумента. Поэтому мне нужно преобразовать Clob в String. Вот метод разбора -

public static Clob parse(Clob clob) {
    String value = clobToString(clob);

    if (!isEmpty(value)) {
        return stringToClob(Jsoup.parse(value).text().trim());
    }

    return null;
}

Этот метод выполняет преобразование из Clob в String -

private static String clobToString(Clob clob) {
    StringBuilder sb = new StringBuilder();

    if (clob == null) {
        return null;
    }

    try {
        Reader reader = clob.getCharacterStream();
        BufferedReader br = new BufferedReader(reader);

        String line;

        while (null != (line = br.readLine())) {
            sb.append(line);
        }

        br.close();
    } catch (IOException e) {
        // handle this exception
    } catch (SQLException e) {
        //e.printStackTrace();
    }

    return sb.toString();
}

И снова мне нужно преобразовать String обратно в Clob, прежде чем возвращать проанализированное значение.

private static Clob stringToClob(String value) {
    if (isEmpty(value)) {
        return null;
    }

    Clob myClob = null;

    try {
        myClob = new SerialClob(value.toCharArray());
    } catch (SQLException e) {
        //e.printStackTrace();
    }

    return myClob;
}

При вызове функции -

create or replace FUNCTION parse(value in CLOB) 
   RETURN CLOB  
      AS LANGUAGE JAVA NAME 'HtmlParser.parse(java.sql.Clob) return java.sql.Clob';

У меня следующая ошибка -

ORA-00932: несогласованные типы данных: ожидалось, что возвращаемое значение, которое является экземпляром определенного пользователем класса Java, конвертируемого в тип Oracle, получило объект, который не может быть преобразован

Поскольку я использовал javax.sql.rowset.serial.SerialClob для инициализации Clob. Я не хочу использовать Connection в этом случае. Есть ли способ обойтись?


person Erfan Ahmed    schedule 05.01.2020    source источник
comment
Эрфан, как говорится в сообщении, вы создаете функцию, которая принимает на вход CLOB, а в java вы ожидаете строку. Итак, Oracle НЕ преобразует строку при ее передаче (как вы говорите, что вы передаете CLOB), и Java-код жалуется. Итак, либо объявите (значение в varchar2), либо в своем классе java скажите ему, что он ожидает clob.   -  person gsalem    schedule 05.01.2020


Ответы (1)


Ваше объявление метода Java в хранимой процедуре Oracle Java с использованием String будет работать только для параметра VARCHAR2.

вот простой пример

create or replace and compile java source named  "HelloVarchar" as
public class HelloVarchar
{
  public static String world(String txt)
  {
    return "Hello " + txt;
  }
};
/

CREATE or replace FUNCTION parse_varchar(value in VARCHAR2) 
  RETURN VARCHAR2  
   AS LANGUAGE JAVA NAME 'HelloVarchar.world(java.lang.String) return java.lang.String';
/

Чтобы использовать CLOB, можно было объявить oracle.sql.CLOB, но этот класс явно устарело с компенсацией с помощью java.sql. Clob

Вот тривиальный пример, возвращающий только параметр

create or replace and compile java source named  "HelloClob" as
import java.sql.Clob;
import java.sql.SQLException;

public class HelloClob
{
  public static Clob world(Clob txt) throws SQLException 
  {
    return  txt;
  }
};
/

CREATE or replace FUNCTION parse_clob(value in CLOB) 
  RETURN CLOB  
   AS LANGUAGE JAVA NAME 'HelloClob.world(java.sql.Clob) return java.sql.Clob';
/
person Marmite Bomber    schedule 05.01.2020
comment
Я ценю ваш ответ и время, которое вы на него потратили. Я тоже пробовал этот подход. Но возникла проблема. Я обновил свой вопрос. Не могли бы вы показать мне немного света? - person Erfan Ahmed; 06.01.2020
comment
@ErfanAhmed на самом деле мне тоже не удалось рабочий пример с Clob. Я использовал для аналогичного случая (теперь устаревший) класс oracle.sql.CLOB. Моя уловка заключалась в использовании процедуры Java с двумя параметрами CLOB (ввод и вывод), а функция function представляла собой простой PL / SQL, обертывающий процедуру и создающий временный CLOB с использованием dbms_lob.createtemporary . Вы можете попробовать это как обходной путь, скомпилировав классы с предупреждением игнорировать устаревшее. Удачи! - person Marmite Bomber; 06.01.2020
comment
Может быть, @KuassiMensah;) - person Marmite Bomber; 06.01.2020