这个项目使用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>
问题摘要:
super.currentSession()
还是super.getSessionFactory().openSession()
?这是我的代码
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
感谢您的帮助
答案 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();它会返回你的异常。