我尝试使用存储过程将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/