簡體   English   中英

休眠延遲異常無法初始化代理-無會話

[英]hibernate lazy exception could not initialize proxy - no Session

這個項目使用spring springMVC休眠

我如何使用"org.springframework.orm.hibernate4.support.OpenSessionInViewFilter"解決lazy load問題"could not initialize proxy - no Session"

在CommonDao中,如果我將Session session = super.currentSession()設置Session session = super.currentSession()則延遲加載會導致異常“無法初始化代理-沒有Session”。

如果我使用Session session = super.getSessionFactory().openSession() ,它將不會導致異常,但是...在瀏覽器請求大約30次之后,它無法獲取任何數據。沒有更多的會話可以使用(似乎OpenSessionInViewFilter沒有為每個請求關閉任何會話),但是我確定我已經在web.xml配置了"OpenSessionInViewFilter"

問題總結:

  1. web.xml中的“ OpenSessionInViewFilter”是否正確?
  2. 在CommonDao中,我應該使用super.currentSession()還是super.getSessionFactory().openSession()嗎?
  3. 為什么“ OpenSessionInViewFilter”不起作用? 需要更多配置?

這是我的代碼

道:

@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("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>  

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>

當我使用此網址時:

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

謝謝你的幫助

相對於您的第一個問題。 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

當您獲得對象並且有一些列表未通過查詢中的提取加入時,通常會發生這種情況。 因此,不會從數據庫中檢索信息。 嘗試通過添加左聯接來修改您的條件。

然后:

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

當您訪問getMealPackages();時 它返回您的異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM