我正在开发一个Java项目,该项目包含 PostgresSQL 9.0 数据库层,使用 JDBC 。 SQL包含在函数中,在 Java 中执行,就像使用JDBC的存储过程一样。
数据库需要 header-detail 方案,详细记录需要标题的外键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();
非常感谢您的精彩回答!
答案 0 :(得分: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”。
答案 1 :(得分:2)
虽然您似乎已经解决了当前的问题,但如果您在Java EE容器内运行,则可能需要查看JTA。结合EJB3.1 *的JTA允许您进行声明式事务控制,并根据我的经验大大简化事务管理。
*不用担心,EJB3.1比以前的EJB规范更简单,更简洁,更少可怕。