【问题标题】:Oracle Store Procedure with BLOB parameter带有 BLOB 参数的 Oracle 存储过程
【发布时间】:2013-11-17 01:00:48
【问题描述】:

您好,我是使用这项技术 (Oracle SP) 的新手,所以我遇到了一些问题,

具体来说,我想在存储过程中插入一个 BLOB 对象,目前我使用的是 spring、jboss、java 和 oracle,我的 SP 比简单:

PROCEDURE SAVE_DATA(data IN BLOB, date IN DATE) IS
next_id number;
BEGIN
  select s_id.nextval into next_id from dual;

  INSERT INTO DATA_TABLE( id, data , date)
  values
  (next_id, data , date);
  COMMIT;

  EXCEPTION
   WHEN OTHERS THEN
     RAISE_APPLICATION_ERROR(-20101,''||SQLCODE ||'-'||SUBSTR(SQLERRM,1,500));
  END SAVE_FAILED_EMAIL;

所以在java端,我做这样的事情:

  WrappedConnection wrappedCon = (WrappedConnection) this.getDataSource().getConnection();
        con = (OracleConnection) wrappedCon.getUnderlyingConnection();
        byte[] bytes= IOUtils.toByteArray(input);
        blobObj=con.createBlob(bytes);

  execute(new CallableStatementCreator() {

        public CallableStatement createCallableStatement(Connection con)
                throws SQLException {
             String procedure = "call SAVE_DATA(?,?)";

                CallableStatement stm=con.prepareCall(procedure);

                stm.setBlob(1, blobObj);
                stm.setDate(2, date);
            return stm;
        }
    }, new CallableStatementCallback<Map<Integer,Object>>() {

        public Map<Integer, Object> doInCallableStatement(CallableStatement cs) 
        throws SQLException,DataAccessException {
            cs.execute();
            return null;
        }} 
    );
    con.commit();
    con.close();

但是当我运行这部分代码时,我得到了来自 DB 端的下一个异常 "ORA-22927 指定了无效的 LOB 定位器"

【问题讨论】:

    标签: java oracle stored-procedures blob


    【解决方案1】:

    这个有点棘手。您遇到的第一个问题是 Oracle 需要专有的 BLOB 和 CLOB 实例;这是来自 Spring OracleLobHandler 的 javadoc:

    虽然大多数数据库都能够使用 DefaultLobHandler,但 Oracle 9i(或更具体地说,Oracle 9i JDBC 驱动程序)只接受 通过自己的专有 BLOB/CLOB API 创建的 Blob/Clob 实例,以及 另外不接受 PreparedStatement 的大流 对应的setter方法。

    但是当您在 JBoss 中工作时,您还需要一个 NativeJdbcExtractor,以便 Spring 可以从 JBoss thread pool wrapper 解包底层连接,然后将 lob 插入 Spring JdbcTemplate。

    所以,这里是您需要更改的代码:

    // ...
    final byte[] bytes= IOUtils.toByteArray(input);
    
    final OracleLobHandler lobHandler = new OracleLobHandler();
    final lobHandler.setNativeJdbcExtractor(new JBossNativeJdbcExtractor());
    // ...
    new CallableStatementCreator() {
    
        public CallableStatement createCallableStatement(Connection con)
                throws SQLException {
             String procedure = "call SAVE_DATA(?,?)";
    
                CallableStatement stm=con.prepareCall(procedure);
    
                lobHandler.getLobCreator().setLobAsBytes(smt, 1, bytes, bytes.length);
                stm.setDate(2, date);
            return stm;
        }
    }
    // ...
    

    【讨论】:

      【解决方案2】:

      对于那些寻求使用存储过程/查询插入 BLOB 的 Spring jdbc 模板解决方案的人,以下语法对我有用:

      通过查询插入

      ByteArrayInputStream inputStream = new ByteArrayInputStream(file.getBytes());
      ps.setBlob(1, inputStream);
      

      通过存储过程调用插入

      Map<String, Object> inParams = new HashMap<>();
      inParams.put("pi_some_id", id);
      inParams.put("pi_file_blob",  new SqlLobValue(file.getBytes()));        
      SqlParameterSource sqlParameterSource = new MapSqlParameterSource(inParams);        
      SqlParameter[] sqlParameters = {
                      new SqlParameter("pi_some_id", Types.VARCHAR),
                      new SqlParameter("pi_file_blob", Types.BLOB),
                      new SqlOutParameter("po_error_flag", Types.VARCHAR),
                      new SqlOutParameter("po_message", Types.VARCHAR)};
              
      SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withoutProcedureColumnMetaDataAccess().
      withProcedureName(storedProcName).withCatalogName(packageName).
      declareParameters(sqlParameters);
          Map<String, Object> storedProcResult = simpleJdbcCall.execute(sqlParameterSource);
      

      【讨论】:

        猜你喜欢
        • 2013-11-02
        • 1970-01-01
        • 2010-09-19
        • 1970-01-01
        • 2011-10-08
        • 2015-01-07
        • 2012-05-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多