如何从 DAO 中的 ServletContext 获取 SessionFactory
Posted
技术标签:
【中文标题】如何从 DAO 中的 ServletContext 获取 SessionFactory【英文标题】:How would I obtain SessionFactory from the ServletContext in the DAO 【发布时间】:2015-12-22 21:32:43 【问题描述】:我创建了一个这样的 DAO:它基于:Hibernate: CRUD Generic DAO
public class Dao
SessionFactory sessionFactory;
// initialise session factory
public User save(User o)
return (User) sessionFactory.getCurrentSession().save(o);
public User get(Long id)
return (User) sessionFactory.getCurrentSession().get(User.class, id);
public User void saveOrUpdate(User o)
sessionFactory.getCurrentSession().saveOrUpdate(o);
现在,如果我的 sessionFactory 在 DAO 或其他类中,这一切都很好。但我的问题是从 servletContextListener 调用 SessionFactory:这是我在监听器中的代码:
public void contextInitialized(ServletContextEvent event)
StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure().build();
try
sessionFactory = new MetadataSources(registry).buildMetadata().buildSessionFactory();
event.getServletContext().setAttribute("factory", sessionFactory);
catch(Exception e)
e.printStackTrace();
StandardServiceRegistryBuilder.destroy( registry );
在这种情况下,除了在 DAO 中实际包装 servletRequest 之外,我如何从 DAO 调用 SessionFactory?
【问题讨论】:
为什么要将 HibernateSessionFactory
存储在 ServletContext
中?关于关注点分离的整个想法是,您不希望您的 MVC 应用程序层必须知道如何访问您的数据,即它不应该从不担心数据/persistence 层完全。你正在做的事情使你的 DAO 完全依赖于你的 web 层,这根本不推荐。
看起来是 XY 问题。您当然不想将 SessionFactory 放在 ServletContext 中并让 DAO 从那里获取它。您应该提供有关应用程序总体设计的一些背景信息。
@Buhake Sindi “为什么要将 Hibernate SessionFactory 存储在 ServletContext 中?” - 我希望它在应用程序启动期间被初始化。我想不出任何其他方式来实现它。
@Serge Ballesta - 这只是一些 CRUD,实用方法很少。
我宁愿 DAO 与 Session
一起工作。如果 DAO 没有会话,则从 SessionFactory
获取它,因为 'sessionFactory' 是每个应用程序生命周期构建一次的线程安全对象。你不必担心它。或者,创建一个单独的 HibernateUtils
类,它会返回一个 SessionFactory
。
【参考方案1】:
我强烈不鼓励将 Hibernate SessionFactory
存储到 Servlet 的 ServletContext
中。另外,让您的 DAO 使用您的 Hibernate Session
。
为了解决您的 Hibernate SessionFactory
实例化一次的问题,我创建了一个单例类来管理它:
/**
*
*/
package za.co.sindi.persistence.util;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
/**
* This is a Hibernate utility class that strictly uses the Hibernate 4.x library.
*
* @author Buhake Sindi
* @since 26 November 2012
*
*/
public final class HibernateUtils
private static final Logger logger = Logger.getLogger(HibernateUtils.class.getName());
private static Configuration configuration;
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> sessionThread = new ThreadLocal<Session>();
private static final ThreadLocal<Interceptor> interceptorThread = new ThreadLocal<Interceptor>();
static
try
configuration = new Configuration();
serviceRegistry = new StandardServiceRegistryBuilder().build();
sessionFactory = configuration.configure().buildSessionFactory(serviceRegistry);
catch (HibernateException e)
logger.log(Level.SEVERE, "Error intializing SessionFactory.", e.getLocalizedMessage());
throw new ExceptionInInitializerError(e);
/**
* Private constructor
*/
private HibernateUtils()
/**
* @return the sessionFactory
*/
public static SessionFactory getSessionFactory()
return sessionFactory;
/**
* Retrieves the current session local to the thread.
*
* @return Hibernate @link Session for current thread.
* @throws HibernateException when Hibernate has a problem opening a new session.
*/
public static Session getSession()
Session session = sessionThread.get();
if (session == null)
Interceptor interceptor = getInterceptor();
if (interceptor != null)
session = getSessionFactory().withOptions().interceptor(interceptor).openSession();
else
session = getSessionFactory().openSession();
if (session != null)
sessionThread.set(session);
return session;
/**
* Closes the Hibernate Session (created from the <code>getSession()</code> session.
*/
public static void closeSession()
Session session = sessionThread.get();
sessionThread.set(null);
if (session != null && session.isOpen())
session.close();
/**
* Registers a Hibernate @link Interceptor.
* @param interceptor
*/
public static void registerInterceptor(Interceptor interceptor)
interceptorThread.set(interceptor);
/**
* Get the registered Hibernate Interceptor.
* @return
*/
public static Interceptor getInterceptor()
return interceptorThread.get();
在我的 DAO 中,我只是将会话检索为 HibernateUtils.getSession();
。
这样,我的 MVC 应用程序就不会引用我的特定 DAO 实现。
我希望这会有所帮助。
【讨论】:
我应该在哪里实例化它? 它在static
块中实例化并实例化一次.. 您所要做的就是检索Session
。无需担心再次实例化 SessionFactory
,因此它是单例类。
您好,您能解释一下为什么不鼓励将 SessionFactory 存储在 ServletContext 中吗?接缝比静态变量更安全。
@Orden 因为ServletContext
是您的前端应用程序,并且您希望分离您的关注点,即您的表示层必须永远不知道存储库层的复杂性。以上是关于如何从 DAO 中的 ServletContext 获取 SessionFactory的主要内容,如果未能解决你的问题,请参考以下文章
如何从 JAX-WS Web 服务中访问 ServletContext?
如何在 Spring MVC 中的不同类中创建动态 bean
如何解决 BeanDefinitionStoreException:IOException 从 ServletContext 资源 [/WEB-INF/dispatcher-servlet.xml]