hibernate懒惰异常无法初始化代理 - 没有Session

时间:2016-05-19 07:25:05

标签: java spring hibernate

这个项目使用spring springMVC hibernate

我如何使用"org.springframework.orm.hibernate4.support.OpenSessionInViewFilter"来解决lazy load问题"could not initialize proxy - no Session"

如果我设置Session session = super.currentSession()延迟加载导致异常"无法初始化代理 - 没有会话"。

如果我使用Session session = super.getSessionFactory().openSession(),它不会导致异常,但是...在浏览器提出大约30次请求之后它无法获得任何数据。看来sessionFactory有不再需要使用会话(似乎OpenSessionInViewFilter没有为每个请求关闭任何会话),但我确定我已在"OpenSessionInViewFilter" <中配置web.xml / p>

问题摘要:

  1. &#34;的OpenSessionInViewFilter&#34;在web.xml中是正确的吗?
  2. CommonDao中的
  3. 我应该使用super.currentSession()还是super.getSessionFactory().openSession()
  4. 为什么&#34; OpenSessionInViewFilter&#34;没工作?需要更多配置?
  5. 这是我的代码

    DAO:

    @Repository("commonDao")
    public class CommonDao<T> extends HibernateDaoSupport {
    
    @Resource
    public void setSessionFacotry(SessionFactory sessionFacotry) {
        super.setSessionFactory(sessionFacotry);
    }
    
    @SuppressWarnings("unchecked")
    public T LoadEntityById(Class<T> clazz, Object id, String idName) {
        Session session = super.currentSession();// HERE!!!
                                                 //if I use super.getSessionFactory().openSession() , it won't cause the exception, BUT...after about 30 times request from the browser it can't get any datas 
        Criteria cri = session.createCriteria(clazz);
        if (null == idName || idName.length() <= 0) {
            idName = getClass().getName() + "Id";
        }
        cri.add(Restrictions.eq(idName, id));
        List<T> result = cri.list();
        if (null != result && result.size() > 0) {
            return (T) cri.list().get(0);
        }
    
        return null;
    }
    }
    

    MealMenuDao使用commondao.LoadEntityById()方法

    public class MealMenuDaoImpl implements MealMenuDao {
    
    @Autowired
    private CommonDao<MealMenu> commonDao;
    @Autowired
    private SessionFactory sessionFactory;
    
    @Override
    public MealMenu FindEnityById(Long Id) {
        return commonDao.LoadEntityById(MealMenu.class, Id, "mealMenuId");
    }
    }
    

    SERVICE:

    @Service("mealMenuService")
    @Transactional
    public class MealMenuServiceImpl implements MealMenuService {
    
    @Autowired
    private MealMenuDao mealMenuDao;
    
    @Override
    public MealMenu getMealMenuById(Long id) {
        return mealMenuDao.FindEnityById(id);
    }
    

    PO:

    @Entity
    @Component
    public class MealMenu extends BaseDomain {
    
    private Long mealMenuId;
    private String menuName;
    private int menuType;
    private int canteenId;
    private int state;
    private Date createTime;
    private Date editTime;
    private String description;
    
    private Set<MealPackage> mealPackages;
    private Canteen canteen;
    
    @Id
    // @GeneratedValue(generator = "system-uuid")
    // @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @GeneratedValue
    @Column(name = "ID", unique = true, nullable = false)
    public Long getMealMenuId() {
        return mealMenuId;
    }
    
    public void setMealMenuId(Long mealMenuId) {
        this.mealMenuId = mealMenuId;
    }
    
    public String getMenuName() {
        return menuName;
    }
    
    public void setMenuName(String menuName) {
        this.menuName = menuName;
    }
    
    public int getMenuType() {
        return menuType;
    }
    
    public void setMenuType(int menuType) {
        this.menuType = menuType;
    }
    
    public int getState() {
        return state;
    }
    
    public void setState(int state) {
        this.state = state;
    }
    
    public int getCanteenId() {
        return canteenId;
    }
    
    public void setCanteenId(int canteenId) {
        this.canteenId = canteenId;
    }
    
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @JsonSerialize(using = CustomDatetimeSerializer.class)
    public Date getCreateTime() {
        return createTime;
    }
    
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    
    @JsonSerialize(using = CustomDatetimeSerializer.class)
    public Date getEditTime() {
        return editTime;
    }
    
    public void setEditTime(Date editTime) {
        this.editTime = editTime;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    @JsonIgnore
    @ManyToMany(targetEntity = MealPackage.class, fetch = FetchType.LAZY)
    @JoinTable(name = "R_MealPackage_MealMenu", joinColumns = @JoinColumn(name = "MealMenu_ID"), inverseJoinColumns = @JoinColumn(name = "MealPackage_ID"))
    public Set<MealPackage> getMealPackages() {
        return mealPackages;
    }
    
    public void setMealPackages(Set<MealPackage> mealPackages) {
        this.mealPackages = mealPackages;
    }
    
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "CanteenID")
    public Canteen getCanteen() {
        return canteen;
    }
    
    public void setCanteen(Canteen canteen) {
        this.canteen = canteen;
    }
    }
    

    控制器:

    @Controller
    @RequestMapping("/admin/mealMenuManage")
    public class SysAdmin_MealMenuController {
    
    @RequestMapping("/test")
    @ResponseBody
    public Object test(HttpServletRequest request, Long id) {
        MealMenu mealMenu = this.mealMenuService.getMealMenuById(id);
        Set<MealPackage> mp = mealMenu.getMealPackages();
        mp.size();
        return mp;
    }
    }
    

    WEB.XML我使用OpenSessionInViewFilter但是它没有工作

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <display-name></display-name>
    
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,classpath:spring-hibernate.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- springMVC config -->
    <servlet>
        <description>spring mvc servlet</description>
        <servlet-name>springMvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <description>spring mvc config file</description>
            <param-name>contextConfigLocation</param-name>
            <param-value>
            classpath:applicationContext.xml
            ,classpath:spring-*.xml
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>springMvc</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>userplatform/index.html</welcome-file>
    </welcome-file-list>
    <!-- openSessionInView config -->
    <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>singleSession</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>*.html</url-pattern>
    </filter-mapping>
    

    的applicationContext.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"
        xsi:schemaLocation="  
        http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-3.0.xsd  
        ">
    
    
        <context:property-placeholder location="classpath:database.properties" />
    
    
    
        <context:component-scan base-package="com.flowingsun.webapp">
            <context:exclude-filter type="annotation"
                expression="org.springframework.stereotype.Controller" />
        </context:component-scan>
    
    </beans>  
    

    弹簧hibernate.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:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="  
        http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
        http://www.springframework.org/schema/tx   
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
        http://www.springframework.org/schema/aop   
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
        http://www.springframework.org/schema/context   
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
            destroy-method="close">
            <!-- MySQL5 -->
            <property name="driverClass" value="${driverClassName}"></property>
            <property name="jdbcUrl" value="${url}"></property>
            <property name="user" value="${username}"></property>
            <property name="password" value="${password}"></property>
            <property name="maxPoolSize" value="40"></property>
            <property name="minPoolSize" value="1"></property>
            <property name="initialPoolSize" value="1"></property>
            <property name="maxIdleTime" value="20"></property>
        </bean>
    
    
    
        <bean id="sessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                    <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                </props>
            </property>
    
            <property name="packagesToScan">
                <list>
                    <value>com.flowingsun.webapp.domain</value>
                </list>
            </property>
        </bean>
    
    
        <bean name="txManager"
            class="org.springframework.orm.hibernate4.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory"></property>
        </bean>
        <tx:annotation-driven transaction-manager="txManager" />
    
    
    </beans>
    

    当我使用这个网址时:

    http://localhost:8080/CommonOrderMealWepApp_Maven/admin/mealMenuManage/test.html?id=1 它报告例外

    异常堆栈:

        HTTP Status 500 - Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.flowingsun.webapp.domain.MealMenu.mealPackages, could not initialize proxy - no Session
    
    type Exception report
    
    message Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.flowingsun.webapp.domain.MealMenu.mealPackages, could not initialize proxy - no Session
    
    description The server encountered an internal error that prevented it from fulfilling this request.
    
    exception
    
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.flowingsun.webapp.domain.MealMenu.mealPackages, could not initialize proxy - no Session
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:980)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:151)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    root cause
    
    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.flowingsun.webapp.domain.MealMenu.mealPackages, could not initialize proxy - no Session
        org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572)
        org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212)
        org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:153)
        org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)
        com.flowingsun.webapp.controller.SysAdmin_MealMenuController.test(SysAdmin_MealMenuController.java:106)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:483)
        org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:178)
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:444)
        org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:432)
        org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
        org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:968)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:859)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:844)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:151)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    note The full stack trace of the root cause is available in the Apache Tomcat/8.0.32 logs.
    
    Apache Tomcat/8.0.32
    

    感谢您的帮助

1 个答案:

答案 0 :(得分:0)

相对于你的第一个问题。 in CommonDao if it set session = super.currentSession() the lazy load cause the Exception "could not initialize proxy - no Session".

如果您查看堆栈跟踪:

failed to lazily initialize a collection of role:
com.flowingsun.webapp.domain.MealMenu.mealPackages, could not initialize
proxy - no Session

当您获得对象并且有一些列表未通过查询中的fetch加入时,通常会发生这种情况。因此,不会从数据库中检索信息。尝试修改添加左连接的条件。

然后:

Set<MealPackage> mp = mealMenu.getMealPackages();

访问getMealPackages();它会返回你的异常。