首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 事務延伸至 MVC 層:徹底解決 JPA 惰性加載異常

     編輯:Java 相關知識

JPA 作為 EJB 3.0 核心,以簡潔配置、強大預設值橫跨輕重量級架構。但脫離 J2EE 容器管理時,惰性加載 常在視圖層引發 LazyInitializationException:Service 層事務結束導致 EntityManager 關閉,Entity 變為游離狀態,視圖渲染時無法觸發關聯集合載入。

典型失敗場景

// Action 處理器
public Page doList(WebForm form, Module module) {
    NewsDirQueryObject ndqo = new NewsDirQueryObject();
    form.toPo(ndqo);
    IPageList pageList = service.queryDirsByConditions(ndqo); // 事務在此結束
    form.addResult("dirPath", getDirPath(form));
    return module.findPage("list");
}

// Velocity 模板
#foreach($info in ${dir.children})  // 此處觸發惰性加載,拋出異常
    目錄名稱:${info.title}
#end

Spring 宣告式事務配置於 Service 層(propagation="SUPPORTS" read-only="true"),導致查詢方法返回即提交/關閉事務,視圖層無可用 Session。

解決方案:將事務邊界前移至 MVC 處理器

核心思想:讓 Controller 開啟事務,Service 方法加入現有事務。以 EasyJWeb 為例,攔截核心處理器 RequestProcessor.process() 方法:

<aop:config>
    <aop:pointcut id="easyjwebProcessor"
        expression="execution(* com.easyjf.web.RequestProcessor.process(..))"/>
    <aop:advisor advice-ref="txEasyjwebProcessorAdvice"
        pointcut-ref="easyjwebProcessor"/>
</aop:config>

<tx:advice id="txEasyjwebProcessorAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" read-only="true"/>
    </tx:attributes>
</tx:advice>

<bean class="com.easyjf.web.core.DefaultRequestProcessor" name="EasyJWeb-Processor"/>

效果驗證

  • 單一配置修改,全域解決 所有視圖層惰性加載問題。
  • Service 層原有事務配置保持不變,propagation="REQUIRED" 確保其融入外層事務。
  • 適用 Struts、WebWork、Spring MVC 等所有 MVC 框架,本質是調整事務邊界範圍。

補充建議

  1. 若不想擴大事務範圍,可在 Service 層使用 JOIN FETCH 或 @EntityGraph 預載關聯。
  2. Open Session in View 模式同樣可行,但易導致事務過長、連接佔用過久,生產環境需謹慎評估。
  3. EJB 3.0 容器管理持久化上下文(Extended Persistence Context)原生支援跨請求生命週期,架構允許時優先考慮。

事務邊界前移是治本之策,配置簡單、風險可控,是輕量級架構下解決 JPA 惰性加載的最佳實踐之一。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved