Настроить Hibernate со встроенным Tomcat 7 программно
Я пытаюсь настроить встроенный экземпляр Tomcat в моем приложении без каких-либо файлов конфигурации.
Я провел некоторое исследование и на основе этого длинного урока и более короткого урока я извлек следующие шаги:
Создать
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 } }
Добавьте этот слушатель в контекст приложения
Context rootCtx = tomcat.addContext("", base.getAbsolutePath()); rootCtx.getServletContext().addListener("com.example.listeners.HibernateListener"); tomcat.start(); tomcat.getServer().await();
Реализовать
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; } }
Теперь я должен как-то работать с
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;
}