[英]Oracle Store Procedure with BLOB parameter
嗨,我是使用这项技术 (Oracle SP) 的新手,所以我遇到了一些问题,
具体来说,我想在存储过程中插入一个 BLOB object,目前我使用 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();
但是当我运行这部分代码时,我得到来自数据库端的下一个异常“ORA-22927 指定的 LOB 定位器无效”
这个有点棘手。 您在这里遇到的第一个问题是Oracle需要一个专有的BLOB和CLOB实例。 这是来自Spring OracleLobHandler的Javadoc:
尽管大多数数据库都可以使用DefaultLobHandler进行操作,但是Oracle 9i(或更具体地说,Oracle 9i JDBC驱动程序)仅接受通过其专有的BLOB / CLOB API创建的Blob / Clob实例,并且不接受PreparedStatement对应的大型流。设置方法。
但是当您在JBoss中工作时,您还需要一个NativeJdbcExtractor,以便Spring可以从JBoss线程池包装器中解开基础连接,然后将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;
}
}
// ...
对于那些寻求 Spring jdbc 模板解决方案以使用存储过程/查询插入 BLOB 的人,以下语法对我有用:
通过查询插入
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.