spring-mvc - 从 DB 获取 Blob 抛出 "invalid transaction handle"

标签 spring-mvc firebird c3p0 jdbctemplate jaybird

我在从数据库获取结果时遇到问题。我正在使用 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?

最佳答案

Firebird(以及就此而言的 JDBC)在事务中执行所有操作,因为事务决定了数据的可见性。

在这种特定情况下,选择查询是在事务(可能是自动提交)中执行的,但 blob 访问是在事务提交后完成的。

这会触发此特定异常,因为 Jaybird 知道它需要一个事务来检索 Blob,但即使 Jaybird 有一个访问 Blob 的新事务也无法工作,因为 Blob 句柄仅在查询 Blob 的事务内有效句柄。

您要么需要禁用自动提交,并且仅在检索 blob 之后才提交(从外观上看,这需要对 DAO 进行大量更改),或者您的行映射器需要显式加载blob(例如字节数组)。

另一个选择是确保使用可保存的结果集执行此查询(在这种情况下,Jaybird 会为您将 blob 具体化为 Blob 实例中的字节数组),但我不确定是否JdbcTemplate 允许您指定可保留结果集的使用。

关于spring-mvc - 从 DB 获取 Blob 抛出 "invalid transaction handle",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25420729/

相关文章:

c# - 如何插入 Firebird,主键自动增量?

java - 跨多个 <Host> 元素为公共(public)库共享单个类加载器是否安全?

javascript - 尝试使用 AJAX 发布 JSON 并接收 400

asp.net-mvc - EntityFramework SaveChanges() 抛出并发事务错误

spring - 如何在 Spring 3 中的 Controller 内生成 URI

c# - Firebird 2.5 DB - 如何将多个应用程序连接到同一个 .FDB 文件?

java - C3P0 ComboPooledDataSource.getConnection 方法在部署后带空

java - c3p0 和 hibernate 用户/密码覆盖

spring-mvc - Pivotal 不起作用 java.io.FileNotFoundException : Could not open ServletContext resource [/WEB-INF/templates

html - 缺少 CSS 日期选择器图标