【问题标题】:getting Blob from DB throws "invalid transaction handle"从 DB 获取 Blob 会引发“无效的事务句柄”
【发布时间】:2014-08-21 07:36:44
【问题描述】:

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

【问题讨论】:

    标签: spring-mvc firebird c3p0 jdbctemplate jaybird


    【解决方案1】:

    Firebird(以及就此而言的 JDBC)在事务中完成一切,因为事务决定了数据的可见性。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-23
      • 1970-01-01
      • 2014-05-22
      • 1970-01-01
      相关资源
      最近更新 更多