在本机查询中设置Clob值

时间:2015-07-07 11:02:18

标签: sql oracle jpa clob nativequery

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),我需要传递更多。

  1. 我试图使用方法将Clob值作为java.sql.Clob传递

    final Clob clobValue = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);

  2. 这导致了 java.io.NotSerializableException:org.hibernate.engine.jdbc.ClobProxy

    1. 我尝试使用

      序列化Clob

      final Clob clob = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
      final Clob clobValue = SerializableClobProxy.generateProxy(clob);

    2. 但这似乎为&#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;

      时参数的数量或类型错误
      1. 在阅读了一些关于在实体中使用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;

      2. 时参数的数量或类型错误
      3. 我也可以将值作为字符串传递,只要它不会破坏最大字符串值

      4. 我看过一篇帖子(Using function in where clause with clob parameter)似乎表明唯一的方法是使用&#34;普通的旧JDBC&#34;。这不是一个选择。 我面临一个艰难的最后期限,所以非常欢迎任何帮助。

3 个答案:

答案 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,问题在一阵烟雾中消失了!