我被迫进入一种情况,我正在使用hibernate createNativeQuery来返回一个对象列表数组。
我的查询返回值的(很多)列之一是CLOB。
返回的对象是com.sun.Proxy对象。
我看到了一个问题here 其中
getClass().getInterfaces()
用于识别它是返回的WrappedClob。
但是考虑到我现在在我的Java代码中有这个代理对象,我该如何将它转换为有用的东西...比如String?
答案 0 :(得分:5)
以下代码有助于取消隐藏clob
Link which help me, just add a bit of makeup to the code: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();
}
答案 1 :(得分:0)
您可以尝试使用此代码。可能它并不完美,但它对我有用:) 我正在使用它将常规clob转换为字符串,所以如果你用getWrappedClob()
打开clob对象它也应该工作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);
}
答案 2 :(得分:0)
这不是对 OP 问题的直接回答,因为我不必处理“WrappedClob”的实例。但由于我仍然收到相同的误导性错误消息,我希望有人觉得这很有用:
对我来说,问题是,H2 和 Postgres 的“Clob to String”的休眠实现方式不同。因此,虽然我的测试工作正常,但应用程序会在运行时崩溃。为了解决这个问题,我在不同的环境中实例化了 ClobReader 的不同 bean。 生产环境将使用 Postgres 的 bean 实现,而测试代码使用 H2 bean。
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();
}
}
}
};
}