多層結構是J2EE應用開發的基本模式,很多開發者都會按照多層結構來組織自己的應用(通常分為Facade,Application Service,DAO等層),但是他們往往會選擇在不同層上去控制事務和Hibernate Session的邊界,可千萬不要小看這樣的選擇它會大大影響程序的可維護性和可復用性。
其實在Facade層來控制事務的邊界通常都是最佳選擇。我們知道Facade層的粗粒度接口是直接為用戶請求提供相應服務的,在典型的J2EE環境中通常使用Session Bean來實現Facade層,并且使用CMT。這時如果有的開發人員在其他層次控制了事務如DAO,由于這些層次通常不會采用EJB實現,所以所使用的事務為容器提供的用戶管理事務,根據EJB的事務規范CMT是無法把事務上下文傳遞到用戶管理事務的邊界中的,由于J2EE并不支持事務的嵌套,所以當來自Facade的CMT事務遇見DAO的事務時,內部事務將被掛起,這樣整個事務的情況,就會和設想的業務邏輯產生很大的差異。
并且有時不同業務邏輯的實現會復用DAO提供多個方法,所以很難控制事務的邊界,導致這些方法難以被復用。
對于Hibernate Session,由于存在懶加載的問題,所以開發人員常會預見這樣的異常LazyInitializationException。避免這個問題就要求在關閉session前要裝載好要使用的對象關系域。而這種邏輯通常只與界面顯示內容相關,如果把session的邊界控制放置在DAO或者Application Service中就會使業務邏輯的實現要和界面顯示邏輯混合在一起,我們必須在這些方法中加載那些界面顯示需要的對象關系域。而界面顯示是經常變化的,并且業務邏輯會被多個不同的界面所復用,如果這樣Application Service,DAO中方法的復用性就會大大降低。
把這些工作放在離表現層最近的Facade中便可以避免這些問題。
注意在其他層次中我們不需要控制session的邊界,我們通常采用getCurrentSession()來獲得當前事務中的session,記住這個方法必須在事務上下文存在的情況下才可以調用,并且在事務被提交的時候Hibernate會在自動關閉session,所以我們不要顯示的關閉session.