Настроить Hibernate со встроенным Tomcat 7 программно

Я пытаюсь настроить встроенный экземпляр Tomcat в моем приложении без каких-либо файлов конфигурации.

Я провел некоторое исследование и на основе этого длинного урока и более короткого урока я извлек следующие шаги:

  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 создавать и извлекать данные из связанной базы данных через Hibernate, верно? (сейчас я не уверен, как именно, но это не главное здесь)

Но, к сожалению, я получаю NullPointerException когда я пытаюсь добавить слушателя к коту

Исключение в потоке "main" java.lang.NullPointerException в org.apache.catalina.core.ApplicationContext.addListener(ApplicationContext.java:1278) в org.apache.catalina.core.ApplicationContextFacade.addListener(ApplicationConteavaF64ade)

который указывает на линию rootCtx.getServletContext().addListener("com.example.listeners.HibernateListener");

РЕДАКТИРОВАТЬ 1

Но если я работаю в спящем режиме (без tomcat), он работает нормально. Данные сохраняются без ошибок!

В 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();
}

Так что я думаю, что я настраиваю Hibernate. Ошибка связана с добавлением слушателя...

Что я здесь не так делаю?

2 ответа

После глубокого изучения исходного кода Tomcat я нашел одно из возможных решений:

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

Он делает то, что мне нужно!

Я думаю, что вы пропустили вызов метода cinfigure() из configuraton c сразу после инициализации.

Так должно выглядеть так:

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

или же

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

ОБНОВИТЬ

Чтобы добавить полные свойства в runtim, вы можете создать объект Prperties и использовать метод.

  configuration.buildSettings(Properties props)

Я не уверен, но при использовании этого подхода вполне возможно, что hibernate не ищет hibernate.cfg.xml или.properties в classpath .

ОБНОВИТЬ

Что вы можете дополнительно попробовать вызвать свой метод getConfiguration в методе getSessionFactory вместо вызова его в статическом инициализаторе HibernateUtil expliciteLy

public static getSessionFactory() {
    Configuration c = getConfiguration();
    sessionFactory = c.buildSessionFactory();
    return sessionFactory;
}
Другие вопросы по тегам