在本机查询中设置 Clob 值
Setting a Clob value in a native query
Oracle 数据库。
Spring 使用 Hibernate 的 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),我需要传递的远不止于此。
我尝试使用
方法将 Clob 值作为 java.sql.Clob 传递
最终 Clob clobValue = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
这导致
java.io.NotSerializableException:org.hibernate.engine.jdbc.ClobProxy
我尝试使用
序列化 Clob
最终 Clob clob = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
最终 Clob clobValue = SerializableClobProxy.generateProxy(clob);
但这似乎向 "exact" 函数提供了错误类型的参数,导致
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL错误:29900,SQL状态:99999
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900: 运算符绑定不存在
ORA-06553: PLS-306: 调用 'EXACT'
时参数的数量或类型错误
阅读了一些 post 关于将 Clob 与实体一起使用的内容后,我尝试传入一个字节 [] 但这也提供了错误的参数类型
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL 错误:29900,SQL状态:99999
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900: 运算符绑定不存在
ORA-06553: PLS-306: 调用 'EXACT'
时参数的数量或类型错误
我也可以将值作为字符串传递,只要它不破坏最大字符串值
我看到一个post(Using function in where clause with clob parameter)似乎暗示唯一的方法是使用"plain old 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 堆中。
所以通常的方法是调用数据库函数 empty_clob() 或 dbms_lob.create_temporary(以某种形式)。然后,即使您认为它是 "IN" 参数,您也会从 数据库中获得一个 clob 。然后您可以将任意多的数据写入该定位器(句柄、CLOB),然后您可以将此 CLOB 用作查询的参数。
如果不遵循此模式,您的代码将无法运行。不管你用JPA、SpringBatch还是planJDBC。这个约束是数据库给的。
答案:谢谢你们的回答。当我前段时间解决这个问题时,我应该更新这个。最后我用了JDBC,问题烟消云散!
Oracle 数据库。
Spring 使用 Hibernate 的 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),我需要传递的远不止于此。
我尝试使用
方法将 Clob 值作为 java.sql.Clob 传递最终 Clob clobValue = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
这导致
java.io.NotSerializableException:org.hibernate.engine.jdbc.ClobProxy
我尝试使用
序列化 Clob最终 Clob clob = org.hibernate.engine.jdbc.ClobProxy.generateProxy(stringValue);
最终 Clob clobValue = SerializableClobProxy.generateProxy(clob);
但这似乎向 "exact" 函数提供了错误类型的参数,导致
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL错误:29900,SQL状态:99999
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900: 运算符绑定不存在
ORA-06553: PLS-306: 调用 'EXACT'
阅读了一些 post 关于将 Clob 与实体一起使用的内容后,我尝试传入一个字节 [] 但这也提供了错误的参数类型
(org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144) - SQL 错误:29900,SQL状态:99999 (org.hibernate.engine.jdbc.spi.SqlExceptionHelper:146) - ORA-29900: 运算符绑定不存在 ORA-06553: PLS-306: 调用 'EXACT' 时参数的数量或类型错误
我也可以将值作为字符串传递,只要它不破坏最大字符串值
我看到一个post(Using function in where clause with clob parameter)似乎暗示唯一的方法是使用"plain old 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 堆中。
所以通常的方法是调用数据库函数 empty_clob() 或 dbms_lob.create_temporary(以某种形式)。然后,即使您认为它是 "IN" 参数,您也会从 数据库中获得一个 clob 。然后您可以将任意多的数据写入该定位器(句柄、CLOB),然后您可以将此 CLOB 用作查询的参数。
如果不遵循此模式,您的代码将无法运行。不管你用JPA、SpringBatch还是planJDBC。这个约束是数据库给的。
答案:谢谢你们的回答。当我前段时间解决这个问题时,我应该更新这个。最后我用了JDBC,问题烟消云散!