Sql 在本机查询中设置Clob值

Sql 在本机查询中设置Clob值,sql,oracle,jpa,clob,nativequery,Sql,Oracle,Jpa,Clob,Nativequery,甲骨文数据库 使用Hibernate的Spring JPA 我在将Clob值插入本机sql查询时遇到困难。 调用查询的代码如下所示: @SuppressWarnings("unchecked") public List<Object[]> findQueryColumnsByNativeQuery(String queryString, Map<String, Object> namedParameters) { List<Object[]> resu

甲骨文数据库

使用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> ,  to_clob((:stringValue)),  null  )  =  1 )
查询字符串的格式为

SELECT  COUNT  (  DISTINCT  ( <column>  )  )   FROM  <Table> c  where (exact ( <column> ,  (:clobValue),  null  )  =  1 )
其中,exact,:clobValue,null=1是一个函数,clobValue是一个Clob

我可以按如下方式调整查询:

@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> ,  to_clob((:stringValue)),  null  )  =  1 )
其中,stringValue是一个字符串,但显然这只适用于最大sql字符串大小4000,我需要传入更多

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

最终Clob clobValue=org.hibernate.engine.jdbc.ClobProxy.generateProxystringValue

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

我尝试使用

最终Clob Clob=org.hibernate.engine.jdbc.ClobProxy.generateProxystringValue; 最终Clob clobValue=SerializableClobProxy.generateProxyclob

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

在阅读了一些关于对实体使用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:调用“精确”时参数的数量或类型错误

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

我看过一篇帖子,它似乎建议唯一的方法是使用普通的老JDBC。这不是一个选择。
我正面临一个艰难的最后期限,因此欢迎提供任何帮助。

在这种情况下,似乎需要为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也有类似的解决方法。

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

因此,通常的方法是以某种形式调用DB函数empty\u clob或dbms\u lob.create\u temporary。然后从数据库中获得clob,即使您认为它在参数中。然后,您可以将任意多的数据写入定位器句柄CLOB,然后您可以将此CLOB用作查询的参数


如果不遵循此模式,代码将无法工作。无论您使用JPA、SpringBatch还是PlanJDBC,这都无关紧要。这个约束由数据库给出。

答案:谢谢你们两位的回答。我应该在不久前解决这个问题时更新这个。最后,我使用了JDBC,这个问题在一阵烟雾中消失了

在回答更多问题之前,请先阅读。