我是一名spring新手,正在尝试我的第一个应用程序。我的hibernate状态在呈现视图之前关闭,并且在延迟加载属性(预期行为)方面存在问题。我已将OpenSessionInViewFilter添加到我的web.xml中,并导致以下情况:
java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?
事先,我在使用默认的servlet上下文配置时效果很好(有人可以告诉我为什么吗?)。因此,我添加了以下内容:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/springapp-servlet.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
新的错误消失了..但是仍然从hibernate中获取无会话异常
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.test.model.Store.categories, could not initialize proxy - no Session
我在我的一个控制器中放了一条调试消息,似乎它被初始化了3次。也许我有多个hibernate会话工厂bean实例?我的控制器方法已标记为@Transactional,并且一切正常,直到尝试将会话保持打开状态以使惰性字段可用于视图。
我完整的web.xml(添加了新的上下文,在添加hibernate过滤器之前,没有它也可以正常工作):
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" > <display-name> Spring </display-name> <description> Spring Test </description> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/springapp-servlet.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>hibernateFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <servlet> <servlet-name>springapp</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springapp</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <error-page> <error-code>500</error-code> <location>/error/500</location> </error-page> <error-page> <error-code>404</error-code> <location>/resources/pages/error.html</location> </error-page> </web-app>
springapp-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <context:component-scan base-package="com.test.web.controllers,com.test.service.impl" /> <mvc:annotation-driven /> <mvc:resources mapping="/resources/**" location="/resources/" /> <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?zeroDateTimeBehavior=convertToNull"/> <property name="username" value="spring"/> <property name="password" value="test"/> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="mappingLocations" value="classpath*:com/test/model/hbm/**/*.hbm.xml" /> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQL5Dialect hibernate.show_sql=true </value> </property> </bean> <tx:annotation-driven /> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath" value="/WEB-INF/templates/"/> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver"> <property name="cache" value="true"/> <property name="prefix" value=""/> <property name="suffix" value=".vm"/> <property name="layoutUrl" value="index.vm" /> <!-- if you want to use the Spring Velocity macros, set this property to true --> <property name="exposeSpringMacroHelpers" value="true"/> </bean> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- one of the properties available; the maximum file size in bytes --> <property name="maxUploadSize" value="10000000" /> </bean> <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> <bean id="categoryDAO" class="com.test.dao.hibernate.HibernateCategoryDAO"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="categoryService" class="com.test.service.Categories" scope="singleton"> <property name="dao" ref="categoryDAO"></property> </bean> <bean id="storeDAO" class="com.test.dao.hibernate.HibernateStoreDAO"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <bean id="storeService" class="com.test.service.Stores" scope="singleton"> <property name="dao" ref="storeDAO"></property> <property name="categoryDao" ref="categoryDAO"></property> </bean> </beans>
我的控制器初始化了两次,根ApplicationContext和FrameworkServlet使用了相同的配置。我已经初始化了两个上下文。我已经为根上下文创建了一个名为springapp.xml的配置,并将所有中间层配置移到了那里,并将我的Web层配置留在了springapp- servlet.xml中。
我的web.xml现在看起来像这样,一切正常:
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/springapp.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <filter-name>hibernateFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>sessionFactoryBeanName</param-name> <param-value>sessionFactory</param-value> </init-param> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <servlet> <servlet-name>springapp</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/springapp-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springapp</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>