2012-05-01 23 views
1

我在使用JDBC合併一個包含PostgresSQL 9.0數據庫層的Java項目。 SQL被包裝在函數中,在使用JDBC的存儲過程中,在Java中執行。無法隔離Postgres/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(); 

你輝煌的答案我們將不勝感激!

+0

'DatabaseManager'怎麼樣? –

+1

爲什麼不在'writeHeader'和'writeFault'循環上共享連接(和事務)? – MrJames

+1

我沒有看到任何有關您的代碼不能解決隔離問題。哪裏有問題? –

回答

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」的細節循環。

+0

感謝您的回答,Glenn。雖然我確實發現我的錯誤是隱藏的自動提交,但您的答案將成爲我接下來要做的嘗試。 – MAbraham1

2

儘管看起來您已經解決了您的即時問題,但如果您正在Java EE容器內部運行,則可能需要考慮JTA。 JTA與EJB3.1 *結合在一起,可以讓您進行聲明式事務控制,並極大地簡化了我的經驗。

*不要擔心,EJB3.1比以前的EJB規範簡單得多,乾淨整潔,並且可怕。

+0

謝謝,克雷格,會做。聽起來JTA事務被推薦超過其他事務API。 http://stackoverflow.com/questions/4709864/use-jta-transaction-or-not – MAbraham1