2009-04-21 210 views
22

所以我已經有了這個通用的DAO事情,並且在表面上看起來沒問題。它基本上是在來自Hibernate人員的CaveatEmptor示例應用程序之後進行建模的。DAO模式 - 交易在哪裏適合?

最重要的是,我有一個業務層......應用程序的內核。它完全不瞭解任何特定的DAO實現。

到現在爲止的一切似乎都很好,直到我開始考慮交易。如果交易留給客戶去實施,那麼我在世界上如何保持我在圖層之間進行的很好的分離?也就是說,我現在正在使用Hibernate,而且我並不覺得特別像在業務層代碼中添加特定於hibernate的事務。

我可以創建一個開始,提交和回滾方法,並傳遞給我的業務層實現一個簡單的交易界面...但是...我不知道...

因此,這裏是挑戰:你能否推薦一種方法讓我在不使用單詞Spring(或EJB,或任何其他附加框架)的情況下做到這一點?

回答

12

我記得Martin Fowler建議,以保持在業務層的交易控制,因爲交易是一個業務問題。 (如果您設計了BankAccount類,則交易是域語言的一部分)。

你可以嘗試實現一個TransactionScope在.NET它的工作原理類似的東西

using (TransactionScope ts = new TransactionScope()) 
{ 
    ... 
} 

這是同樣的事情(不完全,但如果你是一個Java的傢伙,這是更明確的給你)

TransactionScope scope = new TransactionScope(); 
try 
{ 
... 
scope.Commit(); 
} 
catch(Exception ex) 
{ 
    scope.Rollback(); 
    throw; 
} 

要將業務層與任何DAO技術分離,您可以在您的域語言中添加一個TransactionFactory,它將返回您使用Commit和Rollback方法定義的ITransactionScope(一個接口)。這樣你的域圖層就不會綁定到你的DAO層,只有TransactionFactory的具體實現是。

ITransactionScope scope = transactionFactory.CreateTransaction(); 
try 
{ 
... 
scope.Commit(); 
} 
catch(Exception ex) 
{ 
    scope.Rollback(); 
    throw; 
} 
+0

嗯,這個工作,但你很快結束了成千上萬的重複的代碼行,任何現實的商業應用程序。 – 2009-09-23 00:23:17

1

您的權利,是應用程序是一個很好的地方,以協調交易,因爲這允許由各種服務/經理/或任何你想要調用他們實現更復雜的行動組成。

一個簡單的解決方案是定義ITransaction接口,並使用某種類型的工廠或DI來隱藏應用程序中實際的ITransaction實現者。我使用nHibernate在.net中翻譯了我自己的內容,基本上我有一個基類,所有我的管理者(在這種情況下,管理者包含一個邏輯集合的實體,如Membership,Order可能使用一個或多個存儲庫)的業務邏輯。我的基類有一個ITransaction BeginTransaction(),它根據配置文件動態創建一個類型。

該類然後與nHibernate的Session一起工作來開始和提交事務。

1

在過去,我已經將事務邏輯放入DAO層次結構的根DAO中,該層次結構與模型中表示系統中單個實體的對象層次結構匹配。也就是說,如果你有和X有很多Y,並且你想要將X和它們的Ys作爲單個複合對象同時存儲和檢索,那麼你的X的DAO也應該爲Y調用DAO。然後,您可以在DAO for X中的add()和update()方法中放入一個事務 - 甚至可以將Y DAO包私有化,以將其隱藏在主業務邏輯中。 即,而不是商業邏輯:

XDAO xDAO = new XDAO(conn); 
xDAO.startTransaction(); 
boolean success = xDAO.add(x); 
if (success) 
    for (Y y : x.getYs()) { 
     success = YDAO.add(y); 
     if (!success) break; 
    } 
if (success) 
    xDAO.commit(); 
else 
    xDAO.rollback(); 

你只想有:

XDAO xDAO = new XDAO(conn); 
xDAO.add(x); 

(與成功/提交/回滾邏輯內部到DAO)

儘管如此,這並不涵蓋了每種情況,而你的可能會有所不同(例如我的JDBC使用JDBC,我不知道Hibernate是如何工作的,或者是否有可能)。

6

在web應用程序,我做什麼來劃分事務是採取HTTP請求/響應循環,其中每個原子業務操作在這些週期中的一個的範圍執行的優點,在一個單一的專用線程。無論使用什麼Web框架(Struts,JSF,GWT等),通常都存在一個可以執行事務分界的「接縫」。在Struts中,它可以是一個基本的Action類。在GWT中,它可以是基本的RemoteServiceImpl類。

因此,使用該訪問中心點打開事務(在允許執行特定於應用程序的代碼之前),如果沒有異常冒泡或者沒有異常回滾(在應用程序特定代碼被執行)。

我在一個龐大而複雜的商業Web應用程序中廣泛應用這種策略,事實證明它工作得很好。

3

也許這對於答案來說有點太晚了,但是如何爲業務層和dao層之間的特定事務創建另一個類?例如。如果要在某個特定的foo()業務方法的事務中運行來自DAO的方法a()和b(),然後創建類似fooInTransaction()的東西來啓動一個事務並在其中調用一個()和b() 。業務方法foo()委託給它。

這將保持業務代碼的清潔和重複可以通過重新分解來避免。