使用spring的jdbcTemplate和存储过程将byte []插入到blob字段中

时间:2014-09-01 15:17:32

标签: spring firebird jdbctemplate jaybird

我尝试使用存储过程将byte[]插入到blob字段中,并获得异常:

  

请求处理失败;嵌套异常是org.springframework.jdbc.BadSqlGrammarException:PreparedStatementCallback;错误的SQL语法[SELECT ID FROM sp_NEWFILE(?,?,?)];嵌套异常是org.firebirdsql.jdbc.field.TypeConversionException:转换为对象时出错。

型号:

public class fileBody { 
private int ID;
private byte[] BODY;
private String FILENAME; //getters an setters}

将其插入数据库

public class FileBodyDaoImpl implements FileBodyDao {

public int insertData(final FileBody fileBody) throws IOException {     
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    LobHandler lobHandler = new DefaultLobHandler();        
    final InputStream in = new ByteArrayInputStream(fileBody.getBODY());
    final int fileSize = in.available();
    Map<String, Object> out = jdbcTemplate.queryForMap("SELECT ID FROM  sp_NEWFILE(?,?,?)",
            new AbstractLobCreatingPreparedStatementCallback(lobHandler) {
                protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException,
                        DataAccessException {
                    ps.setString(1, fileBody.getFILENAME());
                    lobCreator.setBlobAsBinaryStream(ps, 2, in, fileSize);
                    ps.setNull(3, java.sql.Types.INTEGER);
                }
            });     
    int last_inserted = Integer.parseInt(String.valueOf(out.get("ID")));
    return last_inserted;
}

我的存储过程

create or alter procedure sp_NEWFILE (
FILENAME varchar(255),
BODY blob sub_type 0 segment size 80,
USEID integer)
returns (
ID integer)
as
begin
  if (useid is not null) then ID=USEID;
  else ID=GEN_ID(gen_filebody_id,1);
  if ((FILENAME is NULL) or (FILENAME=''))  then FILENAME='UNDEFINED';
  INSERT INTO  t_filebody(ID,BODY,FILENAME) VALUES(:ID,:BODY,:FILENAME);
  suspend;
end^

我得到一个例外:

Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: 
PreparedStatementCallback; 
bad SQL grammar [SELECT ID FROM sp_NEWFILE(?,?,?)]; nested exception is org.firebirdsql.jdbc.field.TypeConversionException: Error converting to object.

版本: jaybird-jdk17-2.2.5; 来源:firebird2.5版本:2.5.1.26351.ds4-2ubuntu0.1;

1 个答案:

答案 0 :(得分:3)

问题是queryForMap不支持PreparedStatementCallback(与例如execute相反),而是您的匿名对象被视为查询执行的正常参数,而Jaybird不支持此对象类型。如果Jaybird支持它,你会收到错误的参数2和3。

通过传递字节数组可以大大简化您的代码:

Map<String, Object> out = jdbcTemplate.queryForMap("SELECT ID FROM sp_NEWFILE(?,?,?)",
        fileBody.getFILENAME(), fileBody.getBODY(), null);

这可以作为Jaybird认为BLOB SUB_TYPE 0java.sql.Types.LONGVARBINARY而JDBC 4.2附录B声明byte[]是默认类型(尽管您也可以将其用作java.sql.Types.BLOB 1}})。

作为旁注,您的存储过程不需要是可选择的(删除SUSPEND使其可执行),并且还可以使用TRIGGER替换该过程来生成主键,通过使用INSERT .. RETURNING ..或通过JDBC生成的密钥工具(后者通过INSERT .. RETURNING ..在Jaybird中实现)来检索值。