使用 spring StoredProcedure 插入 oracle clob IN 参数时克服 32k 限制

overcome 32k limit when inserting oracle clob IN parameter using spring StoredProcedure

环境:oracle 11g,spring-jdbc-3.2.2-RELEASE.jar,JDK 1.7,Oracle UCP 驱动程序。

我有一个存储过程,可以将记录插入到带有 CLOB 列的 table。 SP 在其他 IN 和 OUT 参数中有一个 CLOB 输入参数。我的 Java 代码使用 Spring StoredProcedure 来调用存储过程:

public class MyClass extends StoredProcedure {
    public MyClass(){
       .....
       declareParameter(new SqlParameter("content", Types.CLOB));
       .....
    }

    public void insert(){
       HashMap<String,Object> params = new HashMap<String, Object>(37);
       String bigContent = ....; // which contains ASCII chars in my test
       ....
       params.put("content", new SqlLobValue(bigContent));
       ....
       execute(params);
    }
}

如果 bigContent 的字符数小于 32k,则代码可以正常工作。如果 bigContent 有 50K 个字符,它就不起作用。 我还测试了使用 jdbcTemplate 和 SqlLobValue 直接插入 table,bigContent 有 50K 个字符时一切正常。

我想使用 SP,因为它可以做很多其他事情,而且比分别调用多个 SQL 插入、更新和查询语句更有效。

有人知道如何让它与 SP 一起工作吗?或者如果 bigContent 有 > 32K 个字符,这就是我必须以不同方式处理它的限制?

这取决于您的 Oracle 版本:

  • < 10.1: 你可以把 SetBigStringTryClob 属性 到 true 放在你的 DriverManager.
  • >= 10.1: 你可以使用 OraclePreparedStatement.setStringForClob doc here.

此外,this article可能会对您有所帮助。

Oracle 中 CLOB 的限制是 176TB。 32KB 是 VARCHAR 的限制。您的代码在某处使用从 VARCHAR 到 CLOB 的隐式转换。在 Oracle 中,CLOB 必须是 OUTPUT 参数 - 即使您正在插入它。 Oracle 的 API 假定您在数据库端创建 empty_clob(),然后您 return 应用程序的 LOB 定位器。应用程序然后使用此 LOB 定位器作为文件句柄。

此行为与其他数据库不同。

如果您将数据作为字符串发送,

PL/SQL 的硬性限制为 32k 个字符。如果参数是 CLOB,您可以先创建一个临时 LOB,用数据填充它,然后使用 CLOB 对象调用您的 PL/SQL 过程。

我们遇到了类似的问题,但后来我们在 PL/SQL 中发现了根本原因 - 为“大”参数混合了 VARCHAR2 和 CLOB 类型。

所以最后我们保留了 Java 代码——甚至使用 String 而不是 Clob 将大参数传递给 Java(使用 Spring StoredProcedure)。