`
zengbo0710
  • 浏览: 414368 次
社区版块
存档分类
最新评论

让spring帮助你在MVC层解决JPA的缓迟加载问题

阅读更多
作为EJB3.0的一部分,JPA是一个好东西。其简单的配置方式及强大的默认配置支持,使其可以轻松自由的存在于轻量与重量之间,如果现在您的JavaEE项目,不管是选择轻量级构架还是重量级构架,如果持久层不选择使用JPA,而是用一些ORM框架(如Hibernate、TopLink)的专用API,那么在将来的某一天一定会为这个选择而说出至尊宝那句“假如上天再给我一个机会…”的至理名言。
       下面是一个简单的Entity,是对一个CMS系统中,关于树状信息目录实体类的定义,包括了一些详细的映射的配置信息。
@Entity
public class NewsDir ...{
    @Id
    @GeneratedValue(strategy 
= GenerationType.TABLE)
    
private Long id;// 主键

    @Column(unique 
= true, nullable = false, length = 16)
    
private String sn;// 目录编号

    
private String title; // 目录名称

    @OneToMany(mappedBy 
= "parent", cascade = javax.persistence.CascadeType.REMOVE)
    
private List<NewsDir> children = new java.util.ArrayList<NewsDir>();// 下级目录

    @ManyToOne
    
private NewsDir parent;// 父级目录



}

  当然,跟任何其它优秀的技术一样,JPA也不是完美的,在使用的过程中难免都会出这样那样的问题,这就需要我们程序员具有格物致知的本领,在应用中灵活应付这些问题。
  这里例举一个缓迟加载的问题,以上面的新闻目录Entity为例。对于parnet与children这个一对多的双向关联,为了提高系统效率,children默认使用的是缓迟加载的方式。在一些轻量级的构架中,由于脱离了J2EE容器及事务支持,经常会出现Entity脱离了Persitence Context,变成了detach或EntityManager关闭,导致一些我们预想中的一些功能无法正常运行。
  最常见的就是在使用MVC框架的时候,在表示层无法加载需要缓迟加载的数据。比如,在一个基于EasyJWeb的mvc应用中,action中的方法如下:

public Page doList(WebForm form, Module module) ...{
        NewsDirQueryObject ndqo 
= new NewsDirQueryObject();
        form.toPo(ndqo);
        ndqo.setDel(
true);
        IPageList pageList 
= service.queryDirsByConditions(ndqo);
        CommUtilForTeaec.saveIPageList2WebForm(pageList, form);
        form.addResult(
"dirPath"this.getDirPath(form));
        
return module.findPage("list");
    }

在模板文件中有如下内容:
#foreach($info in ${dir.children})
目录名称:${info.title}
#end

关于业务逻辑层Bean的配置:

 

<aop:config>
                
<aop:pointcut id="CmsManage"
            expression
="execution(* com.easyjf.cms.service.*.*(..))" />
<aop:advisor advice-ref="cmsManageAdvice"
            pointcut-ref
="CmsManage" />            
<tx:advice id="cmsManageAdvice"
        transaction-manager
="transactionManager">
        
<tx:attributes>
            
<tx:method name="get*" propagation="SUPPORTS"
                read-only
="true" />
            
<tx:method name="query*" propagation="SUPPORTS"
                read-only
="true" />
            
<tx:method name="*" propagation="REQUIRED" />
        
</tx:attributes>
    
</tx:advice>
<bean id="cmsManageService"
        class
="com.easyjf.cms.service.impl.CmsManageServiceImpl">    
        
<property name="newsDirDao" ref="newsDirDao" />
    
</bean>

在这里,当mvc层执行到$!info.getChildren()方法的时候,将会用到缓迟加载,由于Spring的事务是配置在service层的,因此在执行service.queryDirsByConditions方法完成后就关闭了事务。因此运行程序就会出现类似下面的错误信息:

2007-03-28 00:39:35,750 ERROR [org.hibernate.LazyInitializationException] - failed to lazily initialize a collection of role: com.easyjf.cms.domain.NewsDir.children, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.easyjf.cms.domain.NewsDir.children, no session or session was closed
 at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:
358)
 at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:
350)
 at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:
97)

  使用其它的mvc如struts、webwork乃至spring mvc都会有这样的问题,问题的核心是在事务启动及结束上,由于我们都习惯于在service层而非mvc配置及使用事务,导致了这样的问题。解决的办法其实很简单,就是把事务的启动放到mvc层,让mvc层的controller来开启事务,而让业务层的方法加入的事务中。比如,在EasyJWeb中,可以通过如下的配置来实现实现在action中开启事务:
  在Spring配置文件中配置EasyJWeb的核心处理器,并把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 name="EasyJWeb-Processor" class="com.easyjf.web.core.DefaultRequestProcessor"/>

  只需要这样简单的配置,你会惊奇的发现,所有缓迟加载及其它由Persitence Context无效而引起的问题均解决了。

       关于easyjweb与spring的集成,有兴趣的朋友请参考stef_wu的《在EasyJWeb使用spring容器》一文。

 

分享到:
评论

相关推荐

    spring mvc jpa单元测试例子

    在Spring MVC和JPA的开发过程中,单元测试是不可或缺的一部分,它可以帮助我们验证代码的正确性,确保系统各个部分能够按预期工作。本例子聚焦于使用Spring的Test注解进行事务管理的单元测试,这对于数据库操作尤其...

    Spring Data JPA的优点和难点.pdf

    - Spring Data JPA可以无缝地与Spring Boot、Spring MVC、Spring Transaction管理等组件集成,为开发者提供了完整的解决方案,降低了系统的复杂性。 然而,尽管Spring Data JPA带来了诸多便利,但在实际使用中也会...

    spring3.0 mvc+hibernate3.6 +jpa 注解实例

    在本实例中,我们探讨的是一个基于Spring 3.0、Hibernate 3.6和Java Persistence API (JPA) 的集成应用,其中充分利用了注解来简化开发过程。这是一个适用于初学者和经验丰富的开发者深入了解这些技术如何协同工作的...

    spring mvc jpa

    Spring MVC 和 JPA 是两种广泛应用于Java开发的技术。Spring MVC 是Spring框架的一部分,是一个轻量级的、模型-视图-控制器(MVC)架构,用于构建Web应用程序。JPA(Java Persistence API)是Java平台上的一个标准,...

    Spring MVC+JPA+Jquery+Flexigrid修改简单示例

    **Spring MVC + JPA + Jquery + Flexigrid 修改简单示例** 在现代Web开发中,Spring MVC作为Java企业级应用的主流框架,为开发者提供了强大的MVC(Model-View-Controller)架构支持。JPA(Java Persistence API)是...

    maven+springmvc+springjpa+hibernate

    在IT行业中,构建高效、可维护的Web应用是至关重要的,而"Maven+SpringMVC+SpringJPA+Hibernate"的组合就是一个常见的解决方案。这个组合提供了全面的开发工具和技术,帮助开发者快速构建基于Java的Web应用程序。...

    Spring集成JPA配置懒加载报错解决方案

    懒加载报错解决方案主要是解决Spring集成JPA配置懒加载时出现的报错问题。懒加载是JPA的特性,它可以在需要时才加载关联对象,以提高应用程序的性能。 报错一:no session 懒加载报错的第一个问题是no session,...

    spring MVC配置详解

    在 web.xml 文件中配置 ContextLoaderListener 和 contextConfigLocation,以便加载 Spring 的配置文件。 ```xml &lt;!-- Spring 配置 --&gt; org.springframework.web.context.ContextLoaderListener ...

    Spring Data JPA

    **Spring Data JPA** 是一个由Spring框架提供的重要模块,它简化了Java应用程序与数据库之间的交互,特别是基于JPA(Java Persistence API)的持久层操作。Spring Data JPA旨在通过提供自动化Repository接口实现、...

    SpringMVC +Hibernate JPA+Spring-data-jpa实例

    **SpringMVC、Hibernate JPA与Spring Data JPA详解** SpringMVC是Spring框架的一部分,主要负责处理Web应用中的模型-视图-控制器(MVC)架构。它提供了一个轻量级、灵活的Web开发解决方案,使开发者可以方便地创建...

    Spring,Spring MVC所需的jar包

    10. **spring-orm-4.1.5.RELEASE.jar**:Spring ORM模块提供了与各种流行ORM框架(如Hibernate、JPA等)的集成,帮助开发者在Spring框架下无缝使用这些ORM技术。 这些jar包的组合使用,使得开发者可以轻松地构建...

    spring3.0MVC中文教材

    - **丰富的功能**: Spring MVC提供了诸如请求映射、视图解析、表单处理等一系列强大的功能,这些功能可以帮助开发者高效地构建和维护Web应用。 - **高度可配置性**: Spring MVC的设计非常灵活,可以轻松地与其他流行...

    spring+mvc

    这个压缩包对于初学者来说是一个很好的学习资源,因为它包含了实际项目的完整结构和配置,可以帮助理解 Spring MVC 和 Hibernate 如何协同工作,以及如何实现基本的登录功能。通过研究和拆解这个示例,开发者可以...

    spring学习: spring mvc基础

    在IT行业中,Spring框架是Java开发中的一个核心组件,尤其在企业级应用开发中占据了重要地位。...通过不断的实践和学习,你可以进一步提升在Spring MVC上的技能,构建出更加复杂且健壮的Web应用程序。

    Struts2+Spring+JPA实例

    Struts2、Spring和JPA是Java开发中常用的三大框架,它们在企业级应用开发中发挥着关键作用。Struts2作为一个成熟的MVC框架,负责处理前端请求和控制业务流程;Spring作为轻量级的IOC(Inversion of Control)和AOP...

    spring-data-jpa-1.1.0.RELEASE

    在实际应用中,Spring Data JPA 1.1.0.RELEASE版本可能需要与Spring MVC或Spring Boot结合使用,通过Spring的依赖注入机制,将Repository注入到Controller中,实现业务逻辑。此外,为了优化性能,可以配置JPA的缓存...

    spring boot+jpa框架

    开发者只需要定义一个Repository接口,Spring Data JPA就能自动生成实现,包括CRUD操作和复杂查询,极大地方便了数据访问层的开发。 在描述中提到的“热部署”功能,是Spring Boot的一大亮点。热部署(Hot ...

    spring data jpa1.7 中文

    - **Bug追踪器**: 项目使用 Jira (https://jira.spring.io/browse/DATAJPA) 追踪 bug 和功能请求,用户可以在此报告问题或者查看已有的问题列表。 - **版本库**: 官方提供的稳定版本库位于 ...

    Struts+Spring+Jpa(hibernate)整合

    在提供的文件中,`Spring+Struts2+Jpa.ppt`可能是整合的讲解或教程,包含详细步骤和注意事项。`applicationContext.xml`是Spring的配置文件,其中会定义bean,包括DataSource、SessionFactory、TransactionManager等...

Global site tag (gtag.js) - Google Analytics