简体   繁体   中英

hibernate lazy exception could not initialize proxy - no Session

this project using spring springMVC hibernate

how could I use "org.springframework.orm.hibernate4.support.OpenSessionInViewFilter" to stove the lazy load problem "could not initialize proxy - no Session"

in CommonDao if I set Session session = super.currentSession() the lazy load cause the Exception "could not initialize proxy - no Session".

if I use Session session = super.getSessionFactory().openSession() , it won't cause the exception, BUT...after about 30 times request from the browser it can't get any datas.it seems that the sessionFactory have no more session to use(it seems OpenSessionInViewFilter didn't close any session for each request), but i'm sure that I already config "OpenSessionInViewFilter" in my web.xml

problem summary:

  1. "OpenSessionInViewFilter" in web.xml is correct?
  2. in CommonDao should I use super.currentSession() or super.getSessionFactory().openSession() ?
  3. why "OpenSessionInViewFilter" didn't work? need more config?

here is my code

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 use commondao.LoadEntityById() method

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:

@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 I use OpenSessionInViewFilter but it dosen't work

<?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>  

Spring-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>

When i use this url:

http://localhost:8080/CommonOrderMealWepApp_Maven/admin/mealMenuManage/test.html?id=1 it report the exception

Exception stack:

    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

thanks for your help

Relative to your first problem. in CommonDao if it set session = super.currentSession() the lazy load cause the Exception "could not initialize proxy - no Session".

If you take a look on your stack trace:

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

This commonly happens when you get your objects and you have some list that are not joined by fetch in query. So information is not retrieved from database. Try to modify your criteria adding left join.

Then:

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

When you access getMealPackages(); it returns your exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM