1

我正在开发一个使用JDBC并入PostgresSQL 9.0数据库层的 Java 项目。SQL 封装在函数中,在Java中执行,就像使用 JDBC 的存储过程一样。

数据库需要一个header-detail方案,详细记录需要 header 的外键 ID。因此,首先写入标题行,然后写入几千条详细记录。 在详细信息完成写入之前,我需要阻止用户访问标题。

您可能会建议包装整个事务,以便在详细记录完成写入之前无法提交标头记录。但是,您可以在下面看到我已将事务隔离到 Java 中的调用:写入标头,然后循环通过详细信息(同时写入详细信息行)。由于数据的庞大,将详细数据传递给函数以执行一项事务是不可行的。

我的问题是:如何在 JDBC 级别包装事务,以便在详细记录完成写入之前不提交标头?

最好的解决方案比喻是 SQL Server 的命名事务,其中事务可以在数据访问层代码(在其他事务之外)启动,并在以后的数据库调用中完成。

以下(简化)代码执行没有错误,但不能解决隔离问题:

DatabaseManager mgr = DatabaseManager.getInstance();
Connection conn = mgr.getConnection();
CallableStatement proc = null;

conn.setAutoCommit(false);
proc = conn.prepareCall("BEGIN TRANSACTION");
proc.execute();

//Write header details
writeHeader(....);
for(Fault fault : faultList) {
    writeFault(fault, buno, rsmTime, dnld, faultType, verbose);
}
proc = conn.prepareCall("COMMIT TRANSACTION");
proc.execute();

您的精彩回答将不胜感激!

4

2 回答 2

3

您是否对 writeHeader 和 writeFault 使用相同的连接?

conn.setAutoCommit(false);

headerProc = conn.prepareCall("headerProc...");
headerProc.setString(...);
headerProc.execute();

detailProc = conn.prepareCall("detailProc...");

for(Fault fault : faultList) {
    detailProc.setString(...);
    detailProc.execute();
    detailProc.clearParameters();
}

conn.commit();

然后你真的应该看看那个细节循环的“addBatch”。

于 2012-05-01T21:26:20.687 回答
2

虽然您似乎已经解决了眼前的问题,但如果您在 Java EE 容器中运行,您可能需要研究 JTA。根据我的经验,JTA 与 EJB3.1* 的结合让您可以进行声明式事务控制并大大简化事务管理。

*别担心,EJB3.1 比以前的 EJB 规范更简单、更干净、更不可怕。

于 2012-05-02T01:35:39.833 回答