Blog

Ponderings of a kind

This is my own personal blog, each article is an XML document and the code powering it is hand cranked in XQuery and XSLT. It is fairly simple and has evolved only as I have needed additional functionality. I plan to Open Source the code once it is a bit more mature, however if you would like a copy in the meantime drop me a line.

Atom Feed

Configuring Hibernate with all Annotated classes in a Package

Supporting Wildcards with a Custom Hibernate Configuration Class

Using the Maven Hibernate plugin, I am automatically generating all Hibernate 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.

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.

An example of a hibernate.cfg file -
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        
        <!-- connection details -->
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost/myDatabase</property>
        <property name="hibernate.connection.username">myUser</property>
        <property name="hibernate.connection.password">myPass</property>
        <!-- @see: http://community.jboss.org/wiki/HibernateCoreMigrationGuide36 -->
        <property name="hibernate.jdbc.use_streams_for_binary">false</property>
        
        <!-- mappings for annotated classes -->
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Customer"/>
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Order"/>
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Item"/>
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Customers"/>
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Stock"/>
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Shipping"/>
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.Billing"/>
        
    </session-factory>
</hibernate-configuration>

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.

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.

Example of a hibernate.cfg file with Wildcard support -
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        
        <!-- connection details -->
        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
        <property name="hibernate.connection.url">jdbc:postgresql://localhost/myDatabase</property>
        <property name="hibernate.connection.username">myUser</property>
        <property name="hibernate.connection.password">myPass</property>
        <!-- @see: http://community.jboss.org/wiki/HibernateCoreMigrationGuide36 -->
        <property name="hibernate.jdbc.use_streams_for_binary">false</property>
        
        <!-- mappings for annotated classes -->
        <mapping class="uk.org.adamretter.org.uk.someapp.web.orm.generated.*"/>
        
    </session-factory>
</hibernate-configuration>

I enabled this by creating my own class AnnotationConfigurationWithWildcard which extends the org.hibernate.cfg.AnnotationConfiguration class. My goal was just to override the parseMappingElement method, however sadly this and a number of other methods were marked as private in the underlying org.hibernate.cfg.Configuration class, 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 JavaAssist which Hibernate already has a dependency on, and the only really new code I added is in the getAllAnnotatedClassNames method.

The Source Code for AnnotationConfigurationWithWildcard.java can be downloaded here.

Personally I am using Spring Framework to wire my application together, and as such I use the following Spring configuration to enable Hibernate and use my custom Hibernate configuration class -

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfigurationWithWildcard"/>
    <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>

Adam Retter posted on Friday, 24th June 2011 at 23.26 (GMT+02:00)
Updated: Friday, 24th 2011 at June 23.26 (GMT+02:00)

tags: HibernateORMwildcardmappingpackageSpringMaven

Add Comment



(will not be shown)






Tag Cloud