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:

 

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

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


9 + = fifteen



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
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.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books