About Michal Jastak

Michał is a Chief Technology Officer in Java Division of AIS.PL, company developing mostly Web Applications of different kind, usually e-Government related.

JPA – Hibernate – Type mapping on package level

When we are finally mature enough to use some custom types mapping in JPA, we usually stuck with some provider specific solution, because JPA itself doesn’t define any mechanism for doing it. Let me show you an example of custom type mapping definition for one of the JPA providers – Hibernate. Suppose that we use Joda Money in our project, and have an entity with property having type Money. There are already pretty nice type mapping implementations for Money, provided by Jadira – User Types project. All we have to do is just let Hibernate know that we want to use specific type mapping. When you look at the Hibernate Docs, Section 5.1.4.1.1: Type, you’ll see few possibilities, starting from the simplest – using @Type annotation on each property having Money type. This choice can be good if you have only one, or very few, properties of this type in your domain mapping. It is very probable that sooner
 
or later, when your project will grow enough, there will be more and more of them, and you end up with many similar lines defining the same type mapping. If you aren’t a big fan of repeating yourself, or you don’t trust in refactorings made by your apprentices, you should consider another way, using @TypeDefs and @TypeDef annotations. As you may read in Hibernate documentation:

‘These annotations can be placed at the class or package level.’

Let’s focus on the second option – package level. We will place these annotations in package-info.java for our domain entities holding package (see: Java Language Specification – 7.4.1. Named Packages). It will look like this:

/**
 * Provides the domain model.
 *
 * @author Warlock
 */
@org.hibernate.annotations.TypeDef(name = "money", defaultForType = Money.class, typeClass = PersistentMoneyAmount.class)
package com.blogspot.vardlokkur.domain;

import org.jadira.usertype.moneyandcurrency.joda.PersistentMoneyAmount;
import org.joda.money.Money;

Now, when you map the property using Money type, you can do it without additional type mapping specification, just like this:

package com.blogspot.vardlokkur.domain;
 
...
import org.joda.money.Money;
 
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
 
...
@Column(name = "SALARY")
private Money salary;
 
...
 
}

One technical note, before you become happy Money mapping user – Because PersistentMoneyAmount uses single column (holding amount) for Money mapping, it requires defining of currency which will be used along with the amount. The default currency can be defined as Persistence Unit property: jadira.usertype.currencyCode

PS. Don’t treat the above Money example as the guideline of Joda Money mapping, there are probably better ways of doing it, see Jadira User Types blog.

Few links for the dessert:

 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

6 Responses to "JPA – Hibernate – Type mapping on package level"

  1. Chuck Krutsinger says:

    Could you break down this line of code in more detail:

    @org.hibernate.annotations.TypeDef(name = “money”, defaultForType = Money.class, typeClass = PersistentMoneyAmount.class)

    What does does defaultForType do?
    What does typeClass do?

    The salary property of the Employee class is of type Money, so how does that relate to PersistentMoneyAmount?

    • PersistentMoneyAmount in Michal’s example is a Hibernate mapping type. It is an implementation of Hibernate specific contracts, usually org.hibernate.type.Type or org.hibernate.usertype.UserType. Those contracts allow Hibernate to convert between Java data and JDBC data, as well as letting it manage value comparisons, value caching, etc.

      defaultForType is a directive telling Hibernate to use this type defintion as the default for all attributes exposed using the indicated type (Money.class in the example). In other words, with that definition in place, anytime Hibernate sees a persistent attribute whose exposed type is Money, this “money” type definition would be used for the mapping. That part hooks into Hibernate’s basic type registry which applications can manage (overriding types as well as supplying custom types). @TypeDef( …, defaultForType=”…”) is just one means of that management. See http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html_single/#types-registry In effect, the defaultForType defines a registration key for the Type mapping

      • Colin McQueen says:

        @org.hibernate.annotations.TypeDef(name = “utcType”, defaultForType = java.util.Date.class,
        typeClass = com.foo.db.hibernate.UTCTimestampType.class)
        package com.foo.db.model;

        I put the annotation on the package but the type is not being picked up. My type is for making Hibernate set dates in the database to UTC and retrieve dates in UTC. That way it does not depend on the server time zone or JVM time zone. Any ideas why Hibernate wouldn’t pick this up?

        • Colin McQueen says:

          I would like to note as well putting the @Type on Date objects in my models works, but this would be tedious as mentioned in the article.

  2. Michał Jaśtak says:

    @google-31f26d1d239610fa624cc3c4f3dae813:disqus – defaultForType defines the type of property for which this @TypeDef is targeted; typeClass defines Hibernate type which will be used (see also http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/#mapping-types-custom )

    In my example the type of property for which we define mapping (using @TypeDef annotation) is Money class, and PersistentMoneyAmount class (which implements Hibernate UserType interface) is responsible for converting database representation of money into Money class instances (and vice versa).

  3. Ray Vanderborght says:

    At the end of the post, the p.s. alludes to a better way of handling it using Jadira.

    Just to fill in what that better way is…

    Put this in persistence.xml

    Now a simple @Column annotation will work:
    @Column(nullable=false)
    private DateTime updated;

    I just went though figuring that out… jadira is good, but the documentation isn’t all that well organized.

Leave a Reply


6 − = three



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close