我从数据库中获取结果时遇到问题。我正在使用firebird,c3p0,JDBCTemplate,SpringMVC。
public class InvoiceDaoImpl implements InvoiceDao {
...
public Invoice getInvoice(int id) {
List<Invoice> invoice = new ArrayList<Invoice>();
String sql = "SELECT ID,FILENAME, FILEBODY FROM T_FILES WHERE id=" + id;
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
invoice = jdbcTemplate.query(sql, new InvoiceRowMapper());
return invoice.get(0);
}....}
二手型号:
public class Invoice {
private int ID;
private Blob FILEBODY;
private String FILENAME;
getters and setters ...
}
RowMapper和Extractor是标准的。
在JSP中我得到一个FileStream并返回文件下载:
@RequestMapping("admin/file/GetFile/{id}")
public void invoiceGetFile(@PathVariable("id") Integer id, HttpServletResponse response) {
Invoice invoice = invoiceService.getInvoice(id);
try {
response.setHeader("Content-Disposition", "inline;filename=\"" + invoice.getFILENAME() + "\"");
OutputStream out = response.getOutputStream();
response.setContentType("application/x-ms-excel");
IOUtils.copy(invoice.getFILEBODY().getBinaryStream(), out);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
catalina.out中:
datasource.DataSourceTransactionManager - Releasing JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@566b1836] after transaction
http-nio-8443-exec-29 DEBUG datasource.DataSourceUtils - Returning JDBC Connection to DataSource
http-nio-8443-exec-29 DEBUG resourcepool.BasicResourcePool - trace com.mchange.v2.resourcepool.BasicResourcePool@4d2dbc65 [managed: 2, unused: 1, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@4ca5c225)
org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544332.
**invalid transaction handle (expecting explicit transaction start)**
at org.firebirdsql.jdbc.FBBlobInputStream.<init>(FBBlobInputStream.java:38)
at org.firebirdsql.jdbc.FBBlob.getBinaryStream(FBBlob.java:404)
我不明白为什么在使用SELECT时需要使用事务处理,而不是UPDATE或INSERT?
答案 0 :(得分:2)
Firebird(以及JDBC)在事务中执行所有,因为事务决定了数据的可见性。
在这种特定情况下,select查询是在事务中执行的(可能是自动提交),但blob访问是在事务提交后完成的。
这会触发此特定异常,因为Jaybird知道它需要一个事务来检索blob,但即使Jaybird有一个新事务访问blob也无法工作,因为blob句柄仅在查询blob的事务中有效处理
您需要禁用自动提交,只需在检索blob之后提交(通过它的外观需要对DAO进行大量更改),或者您的行映射器需要显式加载blob(例如转换为字节数组)。
另一个选择是确保使用可保持的结果集执行此查询(在这种情况下,Jaybird会将blob实现为Blob
实例中的字节数组),但我不确定{{1允许您指定使用可保持的结果集。