【问题标题】:configure hibernate with embedded tomcat 7 programmatically以编程方式使用嵌入式 tomcat 7 配置休眠
【发布时间】:2014-01-19 07:26:57
【问题描述】:

我正在尝试在我的应用程序中配置一个嵌入式 tomcat 实例,而无需任何配置文件。

我做了一些研究,并基于long tutoriala shorter one 我提取了以下步骤:

  1. 创建ServletContextListener

    @WebListener //some articles on the web mentioned, that this would add the 
    //Listener automatically to the app context, but i cant believe that this works in my case
    public class HibernateListener implements ServletContextListener {
    
        public void contextInitialized(ServletContextEvent event) {
            HibernateUtil.getSessionFactory(); // create a factory
        }
    
        public void contextDestroyed(ServletContextEvent event) {
            HibernateUtil.getSessionFactory().close(); // free resources
        }
    }
    
  2. 将该监听器添加到应用上下文

    Context rootCtx = tomcat.addContext("", base.getAbsolutePath());
    rootCtx.getServletContext().addListener("com.example.listeners.HibernateListener");
    
    tomcat.start();
    tomcat.getServer().await();
    
  3. 使用必要的配置实现HibernateUtil

    public class HibernateUtil {
    
        private static final SessionFactory sessionFactory;
    
        static {
            try {
                //should i call .configure() on the returned Configuration here?                
                sessionFactory = getConfiguration()
                        .buildSessionFactory();
            } catch (Throwable ex) {
                System.err.println("Initial SessionFactory creation failed." + ex);
                throw new ExceptionInInitializerError(ex);
            }
    
        }
    
        private static Configuration getConfiguration(){
            Configuration c = new Configuration();
    
            c.setProperty("hibernate.connection.url", "jdbc:hsqldb:hsql://localhost:1234/mydb1");
            c.setProperty("hibernate.connection.username", "SA");
            c.setProperty("hibernate.connection.password", "");
            c.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
    
    
            c.setProperty("dialect", "org.hibernate.dialect.HSQLDialect");
            c.setProperty("cache.provider_class", "org.hibernate.cache.NoCacheProvider");
            c.setProperty("cache.use_query_cache", "false");
            c.setProperty("cache.use_minimal_puts", "false");
            c.setProperty("max_fetch_depth", "3");
    
            c.setProperty("show_sql", "true");
            c.setProperty("format_sql", "true");
            c.setProperty("hbm2ddl.auto", "create");
    
            c.addPackage("com.example.models");
            c.addAnnotatedClass(MyClass.class);
    
            return c;
        }
    
        public static SessionFactory getSessionFactory() {
            return sessionFactory;
        }
    }
    
  4. 现在我应该以某种方式与MyClass 合作,通过休眠从链接数据库创建和检索数据,对吗? (现在我不确定,具体如何,但这不是重点)

但不幸的是,当我尝试将侦听器添加到 tomcat 时,我得到了 NullPointerException

线程“main”中的异常 java.lang.NullPointerException at org.apache.catalina.core.ApplicationContext.addListener(ApplicationContext.java:1278) 在 org.apache.catalina.core.ApplicationContextFacade.addListener(ApplicationContextFacade.java:649)

指向rootCtx.getServletContext().addListener("com.example.listeners.HibernateListener");这一行

编辑 1

但如果我正在运行 hibernate 独立(没有 tomcat)它可以工作 fine。数据正在被正确保存!

HibernateUtil

public static void main(String[] args) {
    MyClass mycls = new MyClass();

    mycls.setMyProperty("My Property");
    Session session = getSessionFactory().openSession();
    Transaction transaction = session.beginTransaction();
    session.save(mycls);
    transaction.commit();
}

所以我认为我配置休眠的方式很好。该错误与添加的侦听器有关...

我在这里做错了什么?

【问题讨论】:

    标签: java hibernate tomcat hsqldb embedded-tomcat-7


    【解决方案1】:

    在深入挖掘 Tomcat 的源代码后,我找到了一种可能的解决方案:

    rootCtx.addApplicationListener(new ApplicationListener("com.example.listeners.HibernateListener", false));
    

    它可以满足我的需要!

    【讨论】:

    • 看看这里。 tomcate 的 applicationlistener 不是初始化的正确位置,因为 hibernate configzration 属于 Web 应用程序。 mrbool.com/working-with-servlet-context-listeners-in-java/29304
    • 嗯。但是当您在 web.xml 中配置侦听器时,tomcat 似乎就是这样做的。请参阅public void configureContext(Context context) 中的source
    • @ali rootctx 是从哪里来的?
    【解决方案2】:

    我认为你错过了配置 c 的方法 cinfigure() 的调用 在你初始化之后。

    所以它应该是这样的::

     SessionFactory sessionFactory =  getConfiguration().confgure().buildSessionFactory();
    

    c = getConfiguration();
    sessionFactory = c.configure().buildSessionFactory();
    

    更新

    为了在运行时添加完整的属性,您可以创建一个 Prperties 对象并使用该方法。

      configuration.buildSettings(Properties props)
    

    我不确定,但使用这种方法,hibernate 可能不会在 classpath 中查找 hibernate.cfg.xml 或 .properties 。

    更新

    您还可以尝试在 getSessionFactory 方法中调用 getConfiguration 方法,而不是在 HibernateUtil 的显式静态初始化程序中调用它

    public static getSessionFactory() {
        Configuration c = getConfiguration();
        sessionFactory = c.buildSessionFactory();
        return sessionFactory;
    }
    

    【讨论】:

    • 感谢您的评论。我已经测试了使用 hibernate 独立运行你的建议并得到了这个异常:Initial SessionFactory creation failed.org.hibernate.HibernateException: /hibernate.cfg.xml not found。我已经更新了我的问题。经过一些测试,我可以看出 hibernate 本身的配置很好。
    • 我建议将 hibernate.cfg.xml 放在您的 web-inf 文件夹中。 hibernate-configuration 元素之间可能为空,因为您在应用程序中设置了所有属性
    • 也看看这个讨论:stackoverflow.com/questions/6074678/…
    • 对不起在WEB-INF/classes下
    • 好吧,正如我在更新的问题中提到的,hibernate 可以很好地执行HibernateUtilmain 方法,而无需使用hibernate.cfg.xml 文件并且无需调用configuration.configure()。为什么你还认为问题出在这里?
    猜你喜欢
    • 2013-02-24
    • 2014-10-20
    • 2011-07-12
    • 1970-01-01
    • 2018-10-21
    • 2016-01-30
    • 1970-01-01
    • 2015-10-30
    相关资源
    最近更新 更多