我在做一个小的项目,锻炼一下自己。请问一下我用的是struts+hibernate,其中有的team(班级)和Student多对一的关系,team对班级设置的是延迟加载,当我在页面中调用team.getStudents()的时候提示session was closed,但是我用不想把student设置为立即加载,有什么办法能使调用team.getStudents()方法时打开session?
[b]问题补充:[/b]
谢谢以上两位的回答,我现在还想问一下,我想让原来的项目保持struts+hibernate保持不变想要实现对students的延迟调用是使用OpenSessionInView 好呢还是自己做一个filter好呢,那个更方便,具体的做法是怎样的?这是我帮别人做得网站,很急,希望高手们能帮一下,谢了!
[b]问题补充:[/b]
如果使用OpenSessionInView 该引入哪些jar包?我感觉这个问题是hibernate很大的一个缺陷啊,为什么hibernate自己不做一个jar包解决呢,而使用spring的,这样很麻烦那
给你粘出几个类的代码,你自己看看,
类HibernateUtil.java,用这个类来管理session和事务
[code="java"]
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.hibernate.exceptions.InfrastructureException;
import org.apache.commons.logging.*;
import javax.naming.*;
/**
@author christian@hibernate.org
*/
public class HibernateUtil {
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static Configuration configuration;
private static SessionFactory sessionFactory;
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
private static final ThreadLocal threadInterceptor = new ThreadLocal();
// Create the initial SessionFactory from the default configuration files
static {
try {
configuration = new Configuration();
sessionFactory = configuration.configure().buildSessionFactory();
// We could also let Hibernate bind it to JNDI:
// configuration.configure().buildSessionFactory()
} catch (Throwable ex) {
// We have to catch Throwable, otherwise we will miss
// NoClassDefFoundError and other subclasses of Error
log.error("Building SessionFactory failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
/**
@return Session the disconnected Session
*/
public static Session disconnectSession()
throws InfrastructureException {
Session session = getSession();
try {
threadSession.set(null);
if (session.isConnected() && session.isOpen())
session.disconnect();
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return session;
}
/**
private static Interceptor getInterceptor() {
Interceptor interceptor =
(Interceptor) threadInterceptor.get();
return interceptor;
}
}
[/code]
如果你用Spring的话,可以用OpenSessionInView
否则可以将session的生命期延长到整个请求域。
做法:先不忙关闭session,做一个Filter,响应请求后再关。
Filter类的doFilter()函数大致实现如下
其中HibernateSessionFactory是你的Hibernate会话工厂类名。
[code="java"]
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) {
chain.doFilter(request, response);
HibernateSessionFactory.closeSession();
}
[/code]
这个就要用到spring里面的OpenSessionInViewFilter,以保证session在页面上打开
借鉴spring的OpenSessionInViewFilter,看下它的代码改造成符合你应用环境的代码
不用引入什么包,spring的OpenSessionInViewFilter就是一个filter,你把spring源码里搞出来这个类放到你的web应用里,就当成是你自己写的一个filter嘛
引入spring可能要改的东西比较多,JE知识库里应该有不少spring的教程。
因为不知道你是否有写Hibernate工厂类,以下仅作参考
明白什么回事后很容易改
新建一个全局的过滤器
[code="java"]
package com.yourcomp;
import com.yourcomp.HibernateSessionFactory;
import javax.servlet.Filter;
//..各种import
public class HbnSessionFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
try {
chain.doFilter(request, response);
HibernateSessionFactory.closeSession();
}
catch (Exception e) {
e.printStackTrace();
}
}
public void init(FilterConfig filterConfig) throws ServletException {}
public void destroy() {}
}
[/code]
web.xml中配置(望文生义,就不解释了……)
[code="xml"]
hbnSessionFilter
com.yourcomp.HbnSessionFilter
hbnSessionFilter
/*
[/code]
简单的filter类如下:
[code="java"]
import org.apache.commons.logging.*;
import javax.servlet.*;
import java.io.IOException;
/**
@author Christian Bauer christian@hibernate.org
*/
public class HibernateFilter implements Filter {
private static Log log = LogFactory.getLog(HibernateFilter.class);
public void init(FilterConfig filterConfig) throws ServletException {
log.info("Servlet filter init, now opening/closing a Session for each request.");
}
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// There is actually no explicit "opening" of a Session, the
// first call to HibernateUtil.beginTransaction() in control
// logic (e.g. use case controller/event handler) will get
// a fresh Session.
try {
chain.doFilter(request, response);
// Commit any pending database transaction.
HibernateUtil.commitTransaction();
} finally {
// No matter what happens, close the Session.
HibernateUtil.closeSession();
}
}
public void destroy() {}
}
[/code]
异常类InfrastructureException
[code="java"]
package org.hibernate.exceptions;
/**
@author Christian Bauer christian@hibernate.org
*/
public class InfrastructureException
extends RuntimeException {
public InfrastructureException() {
}
public InfrastructureException(String message) {
super(message);
}
public InfrastructureException(String message, Throwable cause) {
super(message, cause);
}
public InfrastructureException(Throwable cause) {
super(cause);
}
}
[/code]
学习hibernate的时候参考网上的资料得来的,本人几乎没改给你的,
从spring源码里copy也是好主意,不过可能不太好理解。
[url]http://www.springsource.com/download/community?project=Spring%20Framework[/url]
你的方法效率好低,建议你把session放到线程中。也就是一个线程一个session。
这样你的问题可以解决。效率也快,你去gg看