0

甲骨文数据库。

使用 Hibernate 的 Spring JPA。

我很难将 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 )

其中 "(exact ( , (:clobValue), null ) = 1 )" 是一个函数,而 "clobValue" 是一个 Clob。

我可以将查询调整为如下工作:

SELECT  COUNT  (  DISTINCT  ( <column>  )  )   FROM  <Table> c  where (exact ( <column> ,  to_clob((:stringValue)),  null  )  =  1 )

其中“stringValue”是一个字符串,但显然这只适用于最大 sql 字符串大小(4000),我需要传递的远不止这些。

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

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

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

  1. 我尝试使用序列化 Clob

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

但这似乎为“精确”函数提供了错误类型的参数,导致
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL 错误:29900,SQLState:99999 (org.hibernate.engine.jdbc .spi.SqlExceptionHelper:146) - ORA-29900: 运算符绑定不存在 ORA-06553: PLS-306: 调用“EXACT”时参数的数量或类型错误

  1. 在阅读了一些关于将 Clob 与实体一起使用的帖子后,我尝试传入一个 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: 调用“EXACT”时参数的数量或类型错误

  2. 只要不破坏最大字符串值,我也可以将值作为字符串传递

我看过一篇文章(在带有 clob 参数的 where 子句中使用函数),这似乎表明唯一的方法是使用“普通的旧 JDBC”。这不是一个选择。我面临着一个艰难的最后期限,所以非常欢迎任何帮助。

4

3 回答 3

2

恐怕您对 Oracle 中 CLOB 的假设是错误的。在 Oracle 中,CLOB 定位器类似于文件句柄。并且这样的句柄只能由数据库创建。所以你不能简单地将 CLOB 作为绑定变量传递。CLOB 必须以某种方式与数据库存储相关,因为它最多可以占用 176TB,而类似的东西不能在 Java Heap 中保存。

因此,通常的方法是调用 DB 函数 empty_clob() 或 dbms_lob.create_temporary(以某种形式)。然后,即使您认为它是“IN”参数,您也会数据库中获得一个 clob 。然后,您可以将任意数量的数据写入该定位器(句柄、CLOB),然后您可以将此 CLOB 用作查询的参数。

如果您不遵循此模式,您的代码将无法工作。无论您使用 JPA、SpringBatch 还是计划 JDBC,都没有关系。该约束由数据库给出。

于 2016-05-15T16:58:15.747 回答
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。

于 2016-05-15T16:03:39.170 回答
-2

答案:谢谢两位的回答。当我前段时间解决这个问题时,我应该更新这个。最后我使用了JDBC,问题就烟消云散了!

于 2016-05-25T10:49:49.213 回答