如何在调用 servlet 之前静态初始化 HibernateUtil?

Posted

技术标签:

【中文标题】如何在调用 servlet 之前静态初始化 HibernateUtil?【英文标题】:How to have HibernateUtil statically initialized before servlet is called? 【发布时间】:2014-02-10 21:29:19 【问题描述】:

我希望 java servlet 在 doGet 方法中通过休眠访问数据库,我创建了 HibernateUtil 类以在静态上下文中调用 buildSessionFactory

测试时,我收到错误“tomcat 无法启动”,显然(?)因为 doGet 方法中的 openSession 在 HibernateUtil 类中的 buildSessionFactory 调用之前被调用。

如何确保 HibernateUtil 类在 servlet 中的 doGet 方法之前静态初始化?

这是课程:

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil 

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() 
        try 
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration()
                .configure()
                    .buildSessionFactory();
         catch (Throwable ex) 
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        
    

    public static SessionFactory getSessionFactory() 
        return sessionFactory;
    

我从 doGet() 方法调用如下:

Session session = null;
try 
    session = HibernateUtil.getSessionFactory().openSession();
    // ...

堆栈跟踪如下:

INFO: Starting service Catalina
Feb 10, 2014 12:58:21 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.42
Feb 10, 2014 12:58:21 PM org.apache.catalina.core.ContainerBase startInternal
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/dbwebtest]]
  at java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)
  at java.util.concurrent.FutureTask.get(Unknown Source)
  at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)
  at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:800)
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
  at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
  at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
  at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
  at java.util.concurrent.FutureTask.run(Unknown Source)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
  at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/dbwebtest]]
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
  ... 7 more
Caused by: java.lang.NoClassDefFoundError: org/hibernate/HibernateException
  at java.lang.Class.getDeclaredFields0(Native Method)
  at java.lang.Class.privateGetDeclaredFields(Unknown Source)
  at java.lang.Class.getDeclaredFields(Unknown Source)
  at org.apache.catalina.util.Introspection.getDeclaredFields(Introspection.java:106)
  at org.apache.catalina.startup.WebAnnotationSet.loadFieldsAnnotation(WebAnnotationSet.java:263)
  at org.apache.catalina.startup.WebAnnotationSet.loadApplicationServletAnnotations(WebAnnotationSet.java:142)
  at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:67)
  at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:405)
  at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:881)
  at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:376)
  at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
  at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
  at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5322)
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
  ... 7 more
Caused by: java.lang.ClassNotFoundException: org.hibernate.HibernateException
  at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714)
  at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559)
  ... 21 more

【问题讨论】:

您对错误的解释不正确。向我们展示异常的完整堆栈跟踪。 看起来休眠 jar 文件(或其依赖项之一)不在 webapp 的类路径中,即在 WEB-INF/lib 中:java.lang.NoClassDefFoundError: org/hibernate/HibernateException 确实如此;如果您将其作为答案提交,我可以接受。 【参考方案1】:

看起来休眠 jar 文件(或其依赖项之一)不在 webapp 的类路径中,即在 WEB-INF/lib 中:

java.lang.NoClassDefFoundError: org/hibernate/HibernateException

【讨论】:

【参考方案2】:

您应该使用 Servlet 过滤器来创建 SessionFactory 并打开/关闭会话。 Hibernate 将此称为 Open-Session-In-View 模式,并在此处描述实现:https://community.jboss.org/wiki/OpenSessionInView?_sscc=t

【讨论】:

以上是关于如何在调用 servlet 之前静态初始化 HibernateUtil?的主要内容,如果未能解决你的问题,请参考以下文章

《Head First Servlets & JSP》-5-属性和监听

JavaEE复习二

Servlet基础梳理----Filter

如何在 Keycloak 身份验证之前调用 javax.servlet.Filter

Servlet的生命周期

spring中静态类调用非静态对象的方法