我需要使用Hibernate 从clob Oracle列获取一个字符串,而不使用延迟加载而不使用Criteria查询。它目前返回一个代理类(例如$ Proxy30),但我需要一个String(或者我可以转换为String的东西)。根据调试器,代理用于oracle.sql.CLOB。
当我使用Criteria查询(只有该字段的常规Column注释映射)时,这很好用。但是我们有一个区域可以“构建”一个使用简单的org.hibernate.Query和AliasToEntityMapResultTransformer.INSTANCE的自定义SQL查询,这就是代理问题出现的地方。因为它只是一个org.hibernate.Query,我认为它根本不是指我的注释映射,所以我不认为弄乱注释会有所帮助。
由于此处不使用Criteria查询(我们正在为某些高级搜索报告要求构建查询字符串),我应该如何研究以找到解决方法?或者甚至更好,我做这项工作的努力是什么?
这也适用于Apache Flex应用程序 - 我需要将类型作为String(而不是CLOB)用于客户端的数据传输对象。也许其他Flex开发人员之前已经解决了这个问题?
Query query = getSessionFactory().getCurrentSession().createSqlQuery(sql);
query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List... resultlist = ...query.list();
resultlist.iterator();
//iterate results...
Object shouldBeAString = (Object)result.get("CLOB_COLUMN_NAME");
//The object above should be a String but is a $Proxy30
//Debugger shows an "h" property of type SerializableClobProxy
如果我需要一个自定义的“ResultTransformer” - 任何指向正常文档的链接都会受到赞赏......
答案 0 :(得分:2)
我遇到了同样的问题,各种链接建议将spring升级到4.0.1+并将hibernate升级到4.3.x,但这并没有任何区别。然后我遇到了这个解决了我的问题的链接。作者为Clob编写了一个自定义的ResultTransformer,然后将其设置为您查询的变换器而不是AliasToEntityMapResultTransformer。
http://javatechtricks.blogspot.co.uk/2012/12/hibernate-clob-to-string-conversion.html
以下文章中的代码:
public class MyResultTransformer extends BasicTransformerAdapter {
public final static MyResultTransformer INSTANCE;
static {
INSTANCE = new MyResultTransformer();
}
private MyResultTransformer() {
}
private static final long serialVersionUID = 1L;
@Override
public Object transformTuple(Object[] tuple, String[] aliases) {
Map<String, Object> map = new HashMap<String, Object>();
for (int i = 0; i < aliases.length; i++) {
Object t = tuple[i];
if (t != null && t instanceof Clob) {
Clob c = (Clob) tuple[i];
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
IOUtils.copy(c.getAsciiStream(), bos);
t = new String(bos.toByteArray());
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
map.put(aliases[i], t);
}
return map;
}
}
然后在你的代码中替换
query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
与
query.setResultTransformer(MyResultTransformer.INSTANCE);
此外,替代解决方案可能是更改列类型,我自己没有尝试过。
JDBC大对象 blob和clob类型提供了映射 java.sql包中的Blob和Clob类。如果你正在处理 真正的大价值,你最好的选择是将属性声明为 无论是Blob还是Clob,即使这引入了显式JDBC 依赖于您的数据对象,它可以轻松地让Hibernate充分利用 JDBC功能只在您需要时延迟加载属性值。
如果您不担心数据太大,您可以放心 你自己这个直接的JDBC接口,将属性类型声明为 字符串或字节[],并使用文本或二进制映射它。这些对应 到CLOB和VARBINARY的SQL列类型(Oracle中的RAW,中的BYTEA) PostgreSQL)分别和将值立即加载到 加载对象时的属性。
来源:http://oreilly.com/java/excerpts/harnessing-hibernate/hibernate-types.html
答案 1 :(得分:0)
谢谢你,我修改了一点使用clob方法getSubString
的解决方案:只有一个例外,可以捕获。
public Object transformTuple(final Object[] tuple, final String[] aliases) {
final Map<String, Object> result = new LinkedHashMap<>(tuple.length);
for (int i = 0; i < tuple.length; i++) {
Object object = tuple[i];
if (object instanceof Clob) {
object = clobToString((Clob) object);
}
final String alias = aliases[i];
if (alias != null) {
result.put(alias, object);
}
}
return result;
}
private String clobToString(final Clob clob) {
try {
return clob.getSubString(1, (int) clob.length());
} catch (final SQLException e) {
throw new RuntimeException("Error while converting clob : " + clob, e);
}
}