2009-06-15 98 views
0

什麼是Hibernate的最佳實踐,當回滾外鍵關係,但不想拋出事務(即仍然繼續保存其他數據)?回滾與休眠的外鍵關係

如果我只是通過異常備份堆棧或不執行此回滾,那麼當我試圖保存其他數據(傳遞給持久化的空值或瞬態對象)時,我會遇到一個錯誤,因爲BookingLines是已經堅持。

我目前通過添加新的實體到地圖,然後從實體列表上的失敗刪除它們如下處理回滾:

/* Method that will try to create an invoice but won't roll back the transaction if 
* a currency rate can't be found. 
*/ 
public void createInvoiceFromBooking(Booking booking) { 

    Invoice invoice = new Invoice(); 

    //Map to hold entities that I want to roll back 
    Map<BookingLine, InvoiceLine> addedLines = new HashMap<BookingLine, InvoiceLine>(); 

    try { 
    for(BookingLine bookingLine : booking.getBookingLines()) { 
     InvoiceLIne invoiceLIne = new InvoiceLIne(); 

     //do stuff that can throw exception 
     applyCurrencyRate(invoiceLine); 

     bookingLine.getInvoiceLines().add(invoiceLine); 
     invoice.getInvoiceLines().add(invoiceLine); 

     //add to the "rollback" map 
     addedLines.put(bookingLine, invoiceLine); 
    } 
    } catch (Exception e) { 
    //remove the InvoiceLines from the related entities 
    for(BookingLine bookingLine : addedLines.keySet()) { 
     bookingLine.getInvoiceLines().remove(addedLines.get(bookingLine)); 
    } 
    } 

這工作,但感覺罪惡。有沒有更好的辦法?

A bookingLine.clear()不好,因爲它可能有其他已保存的與其關聯的InvoiceLines。

謝謝。

+1

你所做的就是所謂的'補償交易'。在你的情況下,你想保留當前的交易,同時撤消它的一部分。基本上,你的行爲像提交/回滾不可用於你,但你留在一個單一的事務邊界。我沒有問題,因爲你確實無法使用commit/rollback來完成相同的操作。 – topchef 2009-06-16 04:15:52

回答

2

數據庫的約束是從對象的結構創建的。換句話說,如果你違反約束,你的對象關係就會出現問題。例如,你有A指向B,但沒有B指向A,或者你已經指定了一些關係,不允許有空值,並且有一個空值。

因此,您應該考慮不依賴約束來保持對象模型的一致性。如果實際上通過檢查對象模型確保對象模型是一致的,而不是依賴數據庫來實現這一點,那將會更好,並且更少出錯。

此外,例外情況絕不是一個好主意,不是一個例外情況。有例外來處理錯誤,它們應該是一個「正常」的操作路徑。

由於這個原因,就您的示例而言,我建議您寧願檢查貨幣,如果不存在,也不要將數據添加到持久性存儲中。

+0

+1我經常這樣做,但問題的原因是要確定是否有人有一個好的回滾方法。你不能總是預測每一個結果,依靠異常處理通常是很好的。 – Damo 2009-06-24 08:38:13