<blog:entry xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:blog="http://www.adamretter.org.uk/blog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.adamretter.org.uk/blog http://www.adamretter.org.uk/blog/entry.xsd" status="published" id="918b3704-2bc9-4447-b53b-e33753ef5f47">
    <blog:article timestamp="2011-06-24T23:26:00.000+02:00" author="Adam Retter" last-updated="2011-06-24T23:26:00.000+02:00">
        <blog:title>Configuring Hibernate with all Annotated classes in a Package</blog:title>
        <blog:sub-title>Supporting Wildcards with a Custom Hibernate Configuration Class</blog:sub-title>
        <blog:article-content>
            <xh:p>Using the <xh:a title="Maven Hibernate 3 Plugin" href="http://mojo.codehaus.org/maven-hibernate3/hibernate3-maven-plugin/">Maven Hibernate plugin</xh:a>, I am automatically generating all <xh:a title="Hibernate" href="www.hibernate.org">Hibernate</xh:a> ORM model classes from my existing database schema. The ORM model classes that are generated have Hibernate and JPA (Java Persistence API) Java Annotations in them.</xh:p>
            <xh:p>Sadly, Hibernate does not Scan for annotated classes at startup and so you have to configure Hibernate manually, either through an XML configuration file or programatically, so that it knows about your annotated classes. You have to tell it about each and every class, not only is this quite tedious, its also a pain to maintain as each time you add/remove an entity from your database, you have to remember to add/remove the ORM class to/from the Hibernate config.</xh:p>
            <blog:mini-title>An example of a hibernate.cfg file -</blog:mini-title>
            <xh:pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"&gt;
&lt;hibernate-configuration&gt;
    &lt;session-factory&gt;
        
        &lt;!-- connection details --&gt;
        &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.PostgreSQLDialect&lt;/property&gt;
        &lt;property name="hibernate.connection.driver_class"&gt;org.postgresql.Driver&lt;/property&gt;
        &lt;property name="hibernate.connection.url"&gt;jdbc:postgresql://localhost/myDatabase&lt;/property&gt;
        &lt;property name="hibernate.connection.username"&gt;myUser&lt;/property&gt;
        &lt;property name="hibernate.connection.password"&gt;myPass&lt;/property&gt;
        &lt;!-- @see: http://community.jboss.org/wiki/HibernateCoreMigrationGuide36 --&gt;
        &lt;property name="hibernate.jdbc.use_streams_for_binary"&gt;false&lt;/property&gt;
        
        &lt;!-- mappings for annotated classes --&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Customer"/&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Order"/&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Item"/&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Customers"/&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Stock"/&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Shipping"/&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Billing"/&gt;
        
    &lt;/session-factory&gt;
&lt;/hibernate-configuration&gt;
</xh:pre>
            <xh:p>Considering that our classes are already annotated, having to configure them manually seems unnecessary to me. It would be useful if you could at least use Wildcards in the mappings of the configuration file so that you can indicate an entire package of classes should be mapped.</xh:p>
            <xh:p>So, I decided to write my own Configuration class for Hibernate so that it could support Wildcards in class names, where when encountered it would load all the classes in the package. This massively simplified my hibernate.cfg file and remove the maintenance overhead.</xh:p>
            <blog:mini-title>Example of a hibernate.cfg file with Wildcard support -</blog:mini-title>
            <xh:pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"&gt;
&lt;hibernate-configuration&gt;
    &lt;session-factory&gt;
        
        &lt;!-- connection details --&gt;
        &lt;property name="hibernate.dialect"&gt;org.hibernate.dialect.PostgreSQLDialect&lt;/property&gt;
        &lt;property name="hibernate.connection.driver_class"&gt;org.postgresql.Driver&lt;/property&gt;
        &lt;property name="hibernate.connection.url"&gt;jdbc:postgresql://localhost/myDatabase&lt;/property&gt;
        &lt;property name="hibernate.connection.username"&gt;myUser&lt;/property&gt;
        &lt;property name="hibernate.connection.password"&gt;myPass&lt;/property&gt;
        &lt;!-- @see: http://community.jboss.org/wiki/HibernateCoreMigrationGuide36 --&gt;
        &lt;property name="hibernate.jdbc.use_streams_for_binary"&gt;false&lt;/property&gt;
        
        &lt;!-- mappings for annotated classes --&gt;
        &lt;mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.*"/&gt;
        
    &lt;/session-factory&gt;
&lt;/hibernate-configuration&gt;
</xh:pre>
            <xh:p>I enabled this by creating my own class <xh:span style="font-style: italic">AnnotationConfigurationWithWildcard</xh:span> which extends the <xh:span style="font-style: italic">org.hibernate.cfg.AnnotationConfiguration</xh:span> class. My goal was just to override the <xh:span style="font-style: italic">parseMappingElement</xh:span> method, however sadly this and a number of other methods were marked as private in the underlying <xh:span style="font-style: italic">org.hibernate.cfg.Configuration class</xh:span>, so I had to copy and paste a few methods into my implementation, but otherwise it was very simple. The Scanning for classes with annotations is done by <xh:a title="Javaassist" href="http://www.javaassist.org">JavaAssist</xh:a> which Hibernate already has a dependency on, and the only really new code I added is in the <xh:span style="font-style: italic">getAllAnnotatedClassNames</xh:span> method.</xh:p>
            <xh:p>
                <xh:a title="Java Source Code for AnnotationConfigurationWithWildcard class" href="blog/entries/AnnotationConfigurationWithWildcard.java">The Source Code for AnnotationConfigurationWithWildcard.java can be downloaded here</xh:a>.</xh:p>
            <xh:p>Personally I am using <xh:a title="Spring Framework" href="http://www.springsource.org/about">Spring Framework</xh:a> to wire my application together, and as such I use the following Spring configuration to enable Hibernate and use my custom Hibernate configuration class -</xh:p>
            <xh:pre>
&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;
    &lt;property name="configurationClass" value="org.hibernate.cfg.AnnotationConfigurationWithWildcard"/&gt;
    &lt;property name="configLocation" value="classpath:hibernate.cfg.xml"/&gt;
&lt;/bean&gt;
</xh:pre>
        </blog:article-content>
    </blog:article>
    <blog:tags>
        <blog:tag>Hibernate</blog:tag>
        <blog:tag>ORM</blog:tag>
        <blog:tag>wildcard</blog:tag>
        <blog:tag>mapping</blog:tag>
        <blog:tag>package</blog:tag>
        <blog:tag>Spring</blog:tag>
        <blog:tag>Maven</blog:tag>
    </blog:tags>
</blog:entry>