Version 2

    I'm having sucess with the following methodology in hibernate3 and Tomcat 5.5.x to speed up the Hibernate SessionFactory building by making use of the Configuration().addCacheableFile API call.

     

    This is only recommended for development usage, if you deploy in production I'd recommend using the classic hibernate-cfg.xml and Tomcat's ServletContextListener API to invoke factory building upon application deployment rather than at the first touch of the web-application calling Hibernate.


    The Files

    net/netbauds/catalina/IHibernateCachableFileLoad.java

    This is library code that can be re-used across different web-applications.

    You do not need to modify it, just make it available to the web-application.

    package net.netbauds.catalina;
    
    import org.hibernate.cfg.Configuration;
    
    public interface IHibernateCachableFileLoad {
        public void addMappings(Configuration conf);
    }
    

     

    net/netbauds/catalina/HibernateSessionFactory.java

    Use the static method HibernateSessionFactory.getSessionFactory() to replace your current call to Configuration().configure().buildSessionFactory(). This is usualy in your HibernateSession singleton class, see http://www.hibernate.org/114.html.

    This is library code that can be re-used across different web-applications.

    You do not need to modify it, just make it available to the web-application.

    package net.netbauds.catalina;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    // Singleton sessionFactory
    public class HibernateSessionFactory {
        private static SessionFactory sessionFactory;
    
        public static SessionFactory getSessionFactory() {
            // Don't get from JNDI, use a static SessionFactory
            if (sessionFactory == null) {
                Configuration conf = new Configuration();
                try {
                    Class klass = Class.forName("config.HibernateCachableFileLoad");
                    IHibernateCachableFileLoad hibConf = (IHibernateCachableFileLoad) klass.newInstance();
                    hibConf.addMappings(conf);
                } catch (ClassNotFoundException e) {
                    // NOOP
                } catch (InstantiationException e) {
                    // NOOP
                } catch (IllegalAccessException e) {
                    // NOOP
                }
     
                Configuration confdone = conf.configure();
                if(confdone != null) {
                    // Use default hibernate.cfg.xml
                    sessionFactory = confdone.buildSessionFactory();
                }
            }
    
            return sessionFactory;
        }
    }
    

     

    config/HibernateCachableFileLoad.java

    This is web-application specific, you need to tailor the parts in bold to suit your enviroment. Maybe someone knows an easy way to get the absolute path to the WEB-INF/classes directory from the class loader ? I've just hardwired the path into my code.

    You need to modify:

    * Add all the paths to your *.hbm.xml files (just like you would have in the hibernate-config.xml file).

    package config;
    
    import net.netbauds.catalina.IHibernateCachableFileLoad;
    import org.hibernate.cfg.Configuration;
    
    // This class is webapp specific and allow loading of mapping via
    //  addCachableFile();
    public class HibernateCachableFileLoad implements IHibernateCachableFileLoad {
        public void addMappings(Configuration conf) {
            doFile(conf, "com/mydomain/MyClassFile001.hbm.xml");
            doFile(conf, "com/mydomain/MyClassFile002.hbm.xml");
        }
    
        private void doFile(Configuration conf, String resPath) {
            String path = null;
            URL u = this.getClass().getClassLoader().getResource(resPath);
            if(u != null) {
                path = u.getFile();
                if(path != null)
                    conf = conf.addCacheableFile(path);
            }
            if(path == null || conf == null)
                System.err.println("ERROR: Failed to load: " + resPath);
        }
    }
    

     

    hibernate.cfg.xml

    This leaves my standard hibernate configuration file looking like this. If you are using a hibernate-configuration-3.0.dtd (version 3.0) then you don't need to include any mapping elements.

     

    If you are using older DTD versions then you may need to provide a token Dummy.hbm.xml.

     

    An alternative way maybe to programatically configure the connection.datasource in the HibernateSessionFactory() above and maybe hibernate will allow you to do away with looking and parsing the hibernate.cfg.xml completely and build a working factory with the Configuration you have programatically created.

    You need to modify:

    * The "java:comp/env/jdbc/ConfigureMeDS" to point to your database connection.

    But for now:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration
        PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    
    <hibernate-configuration>
        <session-factory>
            <property name="connection.datasource">java:comp/env/jdbc/ConfigureMeDS</property>
    
            <!-- Mapping files -->
            <!-- <mapping resource="uk/mydomain/Dummy.hbm.xml"/> -->
        </session-factory>
    </hibernate-configuration>
    

     

    If your version of hibernate requires you to have at least one <mapping> element this the following two files might be useful to you. Otherwise thats all there is to it.

     

    uk/mydomain/Dummy.hbm.xml

    Just in case you were not sure.

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC
              "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
              "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="uk.mydomain.Dummy" table="dummy">
           <id name="id" type="long" column="id">
               <generator class="native" />
           </id>
        </class>
    </hibernate-mapping>
    

     

    uk/mydomain/Dummy.java

    Just in case you were not sure.

    package uk.mydomain;
    
    public class Dummy {
        private long id;
        private long getId() {
            return id;
        }
    
        private void setId(long id) {
            this.id = id;
        }
    }