Oracle DB。
Spring JPA使用Hibernate。
我很难将Clob值插入到本机sql查询中。 调用查询的代码如下:
@SuppressWarnings("unchecked")
public List<Object[]> findQueryColumnsByNativeQuery(String queryString, Map<String, Object> namedParameters)
{
List<Object[]> result = null;
final Query query = em.createNativeQuery(queryString);
if (namedParameters != null)
{
Set<String> keys = namedParameters.keySet();
for (String key : keys)
{
final Object value = namedParameters.get(key);
query.setParameter(key, value);
}
}
query.setHint(QueryHints.HINT_READONLY, Boolean.TRUE);
result = query.getResultList();
return result;
}
查询字符串的格式为
SELECT COUNT ( DISTINCT ( <column> ) ) FROM <Table> c where (exact ( <column> , (:clobValue), null ) = 1 )
其中&#34;(exact(,(:clobValue),null)= 1)&#34;是一个功能和&#34; clobValue&#34;是一个Clob。
我可以按如下方式调整查询:
SELECT COUNT ( DISTINCT ( <column> ) ) FROM <Table> c where (exact ( <column> , to_clob((:stringValue)), null ) = 1 )
其中&#34; stringValue&#34;是一个字符串,但显然这只能达到最大sql字符串大小(4000),我需要传递更多。
我试图使用方法将Clob值作为java.sql.Clob传递
final Clob clobValue = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
这导致了 java.io.NotSerializableException:org.hibernate.engine.jdbc.ClobProxy
我尝试使用
序列化Clob final Clob clob = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
final Clob clobValue = SerializableClobProxy.generateProxy(clob);
但这似乎为&#34;确切的&#34;提供了错误的参数类型。函数导致
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL错误:29900,SQLState:99999
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900:运算符绑定不存在
ORA-06553:PLS-306:调用&#39; EXACT&#39;
在阅读了一些关于在实体中使用Clobs的帖子后,我尝试传入一个byte [],但这也提供了错误的参数类型
(org.hibernate.engine.jdbc.spi。 SqlExceptionHelper:144) - SQL错误:29900,SQLState:99999
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900:运算符绑定不存在
ORA-06553:PLS-306:调用&#39; EXACT&#39;
我也可以将值作为字符串传递,只要它不会破坏最大字符串值
我看过一篇帖子(Using function in where clause with clob parameter)似乎表明唯一的方法是使用&#34;普通的旧JDBC&#34;。这不是一个选择。 我面临一个艰难的最后期限,所以非常欢迎任何帮助。
答案 0 :(得分:1)
我担心你对Oracle中CLOB的假设是错误的。在Oracle CLOB中,定位器类似于文件句柄。并且这样的句柄只能由数据库创建。所以你不能简单地将CLOB作为绑定变量传递。 CLOB必须以某种方式与数据库存储相关,因为它可以占用高达176TB,而这样的东西不能保存在Java堆中。
所以通常的方法是调用DB函数empty_clob()或dbms_lob.create_temporary(以某种形式)。然后你会从数据库中得到一个clob ,即使你认为它是&#34; IN&#34;参数。然后,您可以将任意数量的数据写入该定位器(句柄,CLOB),然后您可以将此CLOB用作查询的参数。
如果您不遵循此模式,则代码将无效。无论您使用JPA,SpringBatch还是计划JDBC,都无关紧要。这种约束由数据库给出。
答案 1 :(得分:0)
在这种情况下,似乎需要为Hibernate显式设置参数类型。以下代码对我有用:
Clob clob = entityManager
.unwrap(Session.class)
.getLobHelper()
.createClob(reader, length);
int inserted = entityManager
.unwrap(org.hibernate.Session.class)
.createSQLQuery("INSERT INTO EXAMPLE ( UUID, TYPE, DATA) VALUES (:uuid, :type, :data)")
.setParameter("uuid", java.util.Uuid.randomUUID(), org.hibernate.type.UUIDBinaryType.INSTANCE)
.setParameter("type", java.util.Uuid.randomUUID(), org.hibernate.type.StringType.INSTANCE)
.setParameter("data", clob, org.hibernate.type.ClobType.INSTANCE)
.executeUpdate();
Blob也有类似的解决方法。
答案 2 :(得分:-1)
回答:谢谢你们的回答。我不久前解决了这个问题,我应该更新一下。最后我使用了JDBC,问题在一阵烟雾中消失了!