您的位置:首页 > 编程语言 > Java开发

No qualifying bean of type [javax.persistence.EntityManage] 异常问题的解决

2015-01-20 13:49 603 查看
引言: 在Spring Web项目中一般都会使用OpenEntityManagerInViewFilter来保证JPA session的正常关闭,在笔者的项目中,使用了Spring + Spring Data + JPA + Hibernate来的架构来组织项目,碰到了org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'entityManagerFactory' is defined 的异常信息,将过一番查找之后,方才发现问题是加载顺序的问题....

1. 项目背景介绍

项目中使用的技术有: Spring+Spring Data, JPA, Hibernate等来贯穿项目的主题架构。

2. Session异常关闭的处理机制

在Java Web项目中使用Hibernate经常会遇到LazyInitializationException 。这是因为controller和model层(java代码)将通过JPA的一些启用了延迟加载功能 的领域(如用getRefrence() 方法或者在关联关系中采用fetch=FetchType.LAZY
)返回给view层(jsp代码)的时候,由于加载领域对象的JPA Session已经关闭,导致这些延迟加载的数据访问异常。

这时就可以使用OpenEntityManagerInViewFilter来将一个JPAsession与一次完整的请求过程对应的线程相绑定。

解决办法:

<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
<init-param>
<!-- 指定org.springframework.orm.jpa.LocalEntityManagerFactoryBean在spring配置文件中的名称,默认值为entityManagerFactory
如果LocalEntityManagerFactoryBean在spring中的名称不是entityManagerFactory,该参数一定要指定,否则会出现找不到entityManagerFactory的例外 -->
<param-name>entityManagerFactoryBeanName</param-name>
<param-value>entityManagerFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3. 异常问题的出现

在解决了Session异常关闭之后,在启动服务器的时候,就出现了如下异常信息:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1111)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:276)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1121)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:222)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.lookupEntityManagerFactory(OpenEntityManagerInViewFilter.java:205)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:150)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
从异常信息的分析可知道,OpenEntityManagerInViewFilter中对entityManagerFactory有依赖,需要对其在Spring中声明的实例依赖。 但是没有找到合适的实例。

可是entityManagerFactory的确已经声明在了spring的配置文件之中了。问题在哪里呢?

4. 问题分析以及定位

项目中entityManagerFactory在Spring中的配置文件定义的,经过检查,工作正常,不存在问题。

<beans:bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<!--
<beans:property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
-->
<beans:property name="jpaVendorAdapter">
<beans:bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- hibernate properties definition -->
</beans:bean>
</beans:property>

<beans:property name="persistenceUnitName" value="myPersistenceUnit" />
<beans:property name="packagesToScan">
<beans:list>
<beans:value>com.creditease.bsettle.pay.model</beans:value>
</beans:list>
</beans:property>

<beans:property name="loadTimeWeaver">
<beans:bean
class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</beans:property>
<beans:property name="jpaPropertyMap">
<beans:map>
<beans:entry key="showSql" value="true"></beans:entry>
<beans:entry key="generateDdl" value="false"></beans:entry>
<beans:entry key="hibernate.format_sql" value="true"></beans:entry>
<beans:entry key="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect"></beans:entry>
</beans:map>
</beans:property>
</beans:bean>
于是把问题的怀疑点聚焦在web.xml初始化文件上,是否其中存在什么问题呢?

在web.xml中存在2个地方进行spring实例的初始化操作:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/spring-config.xml</param-value>
</context-param>
第二个位置是:

<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:META-INF/applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
存在错误异常的加载顺序中,entityManagerFactory是在第二个位置中进行加载的。但是OpenEntityManagerInViewFilter是否加载的顺序在其之前,然后就造成了这样的问题呢?

经过试验,果然是加载顺序的问题,将数据库加载的顺序提前即可。

5. 总结

基于上面的问题,我们可以看到, OpenEntityManagerInViewFilter是在系统启动过程中,优先被加载的,同时其对entityManagerFactory有依赖,就要求同时可以初始化entityManagerFactory的实例。

通过调整初始化的顺序,即可很好的修正上述的问题。

参考资料:

1. http://whoosh.iteye.com/blog/1300721
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐