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

标签 spring firebird jdbctemplate jaybird

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

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.

型号:

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;

最佳答案

问题是 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 0 视为 java.sql.Types.LONGVARBINARY 并且 JDBC 4.2 附录 B 声明 byte[] 是默认类型(尽管您也可以将其用作 java.sql.Types.BLOB)。

顺便说一句,您的存储过程不需要是可选择的(删除 SUSPEND 使其可执行),并且该过程也可以通过使用 TRIGGER 来替换。使用 INSERT .. RETURNING .. 生成主键并检索值或通过 JDBC 生成 key 工具(该工具又通过 INSERT .. RETURNING .. 在 Jaybird 中实现)。

关于spring - 使用spring的jdbcTemplate和存储过程将byte[]插入blob字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25608870/

相关文章:

spring - 创建具有多个子上下文的 Spring Boot 应用程序

subquery - 如何在 Firebird 中优化 DELETE .. NOT IN .. SUBQUERY

java - Spring Boot : Transaction with two DB, 如果第二个数据库失败则回滚第一个数据库

java - 如何在 JPA 中重新打开连接

java - 从 Spring Data JpaRepository 返回 @id 字段

sql - 如何在 Firebird 中使用 DISTINCT ON(PostgreSQL 的)?

java - 如何避免将空值发送到java中的sql中

Jdbc 模板的 Java 模糊方法错误

java - 未能执行 AirportWeb 项目的目标

sql - 与 SQL 中的 STUFF 等效的函数(MySQL 中的 GROUP_CONCAT/Oracle 中的 LISTAGG)