Hibernate: Migrating from XML-Based Configuration to Annotation-Based Configuration

Overview

At some point of time, as your project scope grows, the Hibernate mapping XML files are going to get to a point where it becomes very difficult to maintain. This is where the annotation-based configuration comes in. It took me a few years to convince myself that annotation-based configuration is the way to go. Change is hard, yet necessary.

This tutorial covers the following:-

  • Upgrade Hibernate from 3.x to 4.x.
  • Configure Spring-Hibernate integration to replace XML-based configuration with annotation-based configuration.
  • Configure Joda-Time to work properly in Hibernate 4.
  • Activate @Transactional instead of relying on AOP-based transaction.

Maven Dependencies

Change the Hibernate dependency version from 3.x to 4.x. On top of that, add org.jadira.usertype:usertype.core:[version] dependency to get Joda-Time to work properly with Hibernate 4.

Hibernate 3.x

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>3.6.9.Final</version>
</dependency>
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
	<groupId>joda-time</groupId>
	<artifactId>joda-time-hibernate</artifactId>
	<version>1.3</version>
</dependency>

Hibernate 4.x

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.2.6.Final</version>
</dependency>
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
	<groupId>joda-time</groupId>
	<artifactId>joda-time-hibernate</artifactId>
	<version>1.3</version>
</dependency>
<dependency>
    <groupId>org.jadira.usertype</groupId>
    <artifactId>usertype.core</artifactId>
    <version>3.1.0.CR8</version>
</dependency>

By the way, if you don’t know what Joda-Time is or haven’t use it by now, then you should be spanked by the Date God. With that added dependency, the @Type for date field will look a little different ( see here for more info ):-

@Entity
@Table(name = "MrMeow")
public class MrMeow implements Ideable, Serializable {
	...
	
	@Column
	@Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
	private LocalDate whenMeowed;
}

Spring Integration

Hibernate 3.x

This configuration uses Hibernate XML mapping files to configure mappings between the domain objects and the database tables. Further, AOP is used to configure the transaction.

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

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<tx:advice id="txAdvice">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<aop:config proxy-target-class="true">
    <aop:advisor pointcut="execution(* myproject..*.*(..))" advice-ref="txAdvice"/>
</aop:config>

Hibernate 4.x

This configuration scans myproject.domain package, which contains all Hibernate annotated domain classes. Further, it activates @Transactional so that you can place it in your code to manage the transaction.

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>

    <property name="hibernateProperties">
        <props>
			<!-- Configure your Hibernate dialect  -->
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.show_sql">false</prop>
        </props>
    </property>
    <property name="packagesToScan">
        <list>
			<!-- Configure your domain package -->
            <value>myproject.domain</value>
        </list>
    </property>
</bean>

web.xml

Change filter class for OpenSessionInViewFilter.

Hibernate 3.x

<filter>
    <filter-name>hibernateFilter</filter-name>
	<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Hibernate 4.x

<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Domain Classes

Finally, time to annotate your Hibernate domain classes!

Helpful Note

Please make sure you don’t have JPA 1.x in your classpath in the first place. Read java.lang.NoSuchMethodError: javax/persistence/OneToMany.orphanRemoval()Z for more information.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s