有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法在Postgres/JDBC中跨层隔离事务

我正在开发一个Java项目,该项目使用了JDBC集成了Postgressql9.0数据库层。SQL被包装在函数中,在Java中执行,类似于使用JDBC的存储过程

数据库需要一个标题详细信息方案,详细记录需要标题的外键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();

非常感谢您精彩的回答


共 (2) 个答案

  1. # 1 楼答案

    writeHeader和WriteDefault是否使用相同的连接

    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”的细节循环

  2. # 2 楼答案

    虽然看起来您已经解决了眼前的问题,但如果您在JavaEE容器中运行,您可能需要研究JTA。JTA与EJB3相结合。根据我的经验,1*允许您执行声明式事务控制,并大大简化了事务管理

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