Hibernate createNativeQuery, возвращающий прокси-объект для Clob

Я вынужден оказаться в ситуации, когда я использую спящий режим createNativeQuery для возврата массивов списка объектов.

Один из (многих) столбцов, из которых мой запрос возвращает значения, — это CLOB.

Возвращаемый объект — это объект com.sun.Proxy.

Я видел вопрос здесь , где

getClass().getInterfaces()

использовался для определения того, что это возвращаемый объект WrappedClob.

Однако, учитывая, что теперь у меня есть этот прокси-объект в моем коде Java, как мне преобразовать его во что-то полезное... например, строку?


person p45    schedule 11.03.2015    source источник


Ответы (3)


Следующий код помог распаковать clob

Ссылка, которая мне поможет, просто добавьте немного макияжа в код :D

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Clob;
import java.sql.SQLException;
    /**
         * Unproxy clob.
         *
         * @param proxy the proxy
         * @return the string
         * @throws InvocationTargetException the invocation target exception
         * @throws IntrospectionException the introspection exception
         * @throws IllegalAccessException the illegal access exception
         * @throws SQLException the SQL exception
         * @throws IOException Signals that an I/O exception has occurred.
         */
        public static String unproxyClob(Object proxy)
            throws InvocationTargetException, IntrospectionException, IllegalAccessException, SQLException, IOException {
            try {
                BeanInfo beanInfo = Introspector.getBeanInfo(proxy.getClass());
                for (PropertyDescriptor property : beanInfo.getPropertyDescriptors()) {
                    Method readMethod = property.getReadMethod();
                    if (readMethod.getName().contains(GET_WRAPPED_CLOB)) {
                        Object result = readMethod.invoke(proxy);
                        return clobToString((Clob) result);
                    }
                }
            } catch (InvocationTargetException | IntrospectionException | IllegalAccessException | SQLException | IOException exception) {
                LOGGER.fatal(exception);
                throw exception;
            }
            return null;
        }

        /**
         * Clob to string.
         *
         * @param data the data
         * @return the string
         * @throws SQLException the SQL exception
         * @throws IOException Signals that an I/O exception has occurred.
         */
        public static String clobToString(Clob data) throws SQLException, IOException {
            StringBuilder sb = new StringBuilder();
            Reader reader = data.getCharacterStream();
            BufferedReader br = new BufferedReader(reader);
            String line;
            while (null != (line = br.readLine())) {
                sb.append(line);
            }
            br.close();

            return sb.toString();
        }
person Anupam    schedule 27.10.2016
comment
Я думаю, вы забыли добавить этот атрибут в свой класс static String GET_WRAPPED_CLOB = "getWrappedClob". Но :-)!!! - person Leandro Roura Sixto; 20.12.2017
comment
Я потратил почти 1 час, пытаясь понять это, и вы только что решили это! УДИВИТЕЛЬНО - person Gabriel Robaina; 23.08.2019
comment
хорошее решение, только что работал с спящим режимом 4.1.4 весной 3.2.18, большое спасибо... - person ahmettolga; 28.10.2020

Вы можете попробовать этот код. Возможно, это не идеально, но у меня это работает :) Я использую его для преобразования обычного clob в строку, поэтому он также должен работать, если вы разворачиваете объект clob с помощью getWrappedClob()

Clob clob = wrappedClob.getWrappedClob();
String result = null;
Long length = clob.length();
char[] char_array = new char[length.intValue()];
Reader characterStream = clob.getCharacterStream();
try {
    int read = characterStream.read(char_array, 0, length.intValue());
    result = new String(char_array);
} catch (IOException e) {
    log.error("Exception during read from CLOB: " + e);
}
person mrh    schedule 02.06.2015

Это не прямой ответ на вопрос ОП, так как мне не приходилось иметь дело с экземпляром «WrappedClob». Но поскольку я все еще получаю то же вводящее в заблуждение сообщение об ошибке, я надеюсь, что кто-то найдет это полезным:

Проблема для меня заключалась в том, что реализация «Clob to String» в спящем режиме для H2 и Postgres вела себя по-разному. Таким образом, хотя мои тесты работали нормально, приложение вылетало во время выполнения. Чтобы обойти это, я создал разные bean-компоненты ClobReader в разных средах. В производственной среде будет использоваться реализация bean-компонента для Postgres, а в тестовом коде используется bean-компонент H2.

public interface ClobReader {
    String clobToString(Object clob) throws SQLException, IOException;
}


@Bean
public ClobReader clobReaderPostgres() {
    return new ClobReader() {
        @Override
        public String clobToString(final Object clob) {
            if (clob == null) {
                return null;
            }
            return clob.toString();
        }
    };
}


@Bean
@Primary
public ClobReader clobReaderH2() {
    return new ClobReader() {
        @Override
        public String clobToString(final Object obj) throws SQLException, IOException {
            final Clob clob = (Clob) obj;
            try (final Reader reader = clob.getCharacterStream()) {
                try (final StringWriter stringWriter = new StringWriter()) {
                    IOUtils.copy(reader, stringWriter);
                    return stringWriter.toString();
                }
            }
        }
    };
}
person Jonas_Hess    schedule 15.01.2021