Release: Jadira Usertype 3.0.0.CR1 with support for Joda Money 0.6
Thursday, January 19, 2012 at 11:22AM The first candidate build of Jadira Usertype 3.0.0 is now being synchronised to Maven Central. This is quite a big release and represents a large number of significant enhancements for the library.
Change of Naming for Maven Archives
The most immediately visible change is in the names of the Maven archives. Users of 'usertype.jodatime' should now change their dependency to:
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>3.0.0.CR1</version>
</dependency>
Similarly the name of the 'jsr310' archive has changed to 'usertype.extended'. Usertype core contains most usertype functionaliy, whilst extended only contains library code that has dependencies that do not exist in Maven Central. Most users will want to use 'usertype.core'. Today you only need to use 'usertype.extended' if you want to use the JSR 310 usertype mappings. The reason for these changes is to accommodate new features within the usertype library.
Support for Joda Money
The most significant new feature is the inclusion of mappings for Joda Money. This library is a precursor for the eventual implementation of JSR 354, so Joda Money users will benefit from a future migration path as they adopt the JSR, just as Joda Time users can fairly readily switch usertype implementations as they adopt JSR 310. The mappings include mappings for both Money and BigMoney types, and support mapping to decimal or integer columns (for integer columns either the major amount (e.g. Dollars) or minor amount (e.g. cents) can be mapped. Single-column mappings allow a currency to be set either for the particular column (using the 'currencyCode' parameter on the column mapping) or SessionFactory wide (using the JPA or Hibernate property 'jadira.usertype.currencyCode'), whilst multicolumn mappings map the amount and currency each to their own columns.
Updates to Joda Time Support
Joda Time support has been upgraded to 2.0 release of the library. With the upgrade support for two new Joda Time datatypes - MonthDay and YearMonth has been added.
Globalised Configuration Options
The Joda Time and JSR 310 mapping have seen the introduction of system wide configuration options. This is particularly useful because you can set the database timezone and JVM default timezone once using a hibernate or JPA property. The two properties that can be used are 'jadira.usertype.javaZone' and 'jadira.usertype.databaseZone'.
A fourth supported property is 'jadira.usertype.seed'. This can be used to indicate which default implementation of Seed will be used for that SessionFactory.
Autoregistration of User Types in Hibernate 4
A final key new feature is the autoregistration of type mappings in Hibernate 4. This feature (which is not enabled by default) coupled with the use of globalised configuration, will allow you to avoid explicitly including type mappings for many of the commonly supported types.
The types that are autoregistered are:
- PersistentBigMoneyAmount
- PersistentMoneyAmount
- PersistentCurrency
- PersistentCurrencyUnit
- PersistentDateTime
- PersistentDurationAsString
- PersistentInstantAsTimestamp
- PersistentLocalDate
- PersistentLocalTime
- PersistentMonthDayAsString
- PersistentPeriodAsString
- PersistentTimeOfDay
- PersistentYearMonthDay
- PersistentYears
To enable this feature, you need to set the JPA or Hibernate property 'jadira.usertype.autoRegisterUserTypes' to 'true'.
Upgrades
Upgrading from Usertype 2.0 should be relatively straightforward - as most new features are not enabled until the relevant property is set. Remember that Usertype 2.0 and later only support Hibernate 4 and onwards.
Upcoming Features
I am looking at a number of future areas for new functionality in Jadira Usertype. These include the previously mentioned addition of support for JAXB Bindings for the existing mapped types. Further planned changes include a refactor of the support for the JDK Date and Calendar classes and the development of some new domain types - and associated mappings - for types for which no standardised types currently exists. At the top of the list of these types just now are PhoneNumber (which will probably make use of Google's excellent libphonenumber) and Address.
You can find more information on the Usertype project at the project website.
Chris |
15 Comments | 
Reader Comments (15)
Thanks for the new version.
In my opinion the conversion from Date to LocalDate in 3.0.0CR1 (and also older versions) is incorrect.
The current implementation takes timezones in account but a LocalDate has no timezone. DateColumnLocalDateMapper converts a date to a string and then convert this to a DateTime:
DateTimeZone.setDefault(DateTimeZone.forID("Europe/Amsterdam"));
new DateTimeFormatterBuilder().appendPattern("yyyy-MM-dd").toFormatter().parseDateTime("1916-05-01")
This results in java.lang.IllegalArgumentException: Cannot parse "1916-05-01": Illegal instant due to time zone offset transition (Europe/Amsterdam).
Correct code should be: new LocalDate("1916-05-01"). LocalDate is aware that timezones should not be accounted for and correctly transforms the date.
Thanks for the feedback. I have tested and can reproduce the issue. It seems to apply only to certain historical dates (I think where the timezone offset has changed), although it could arise in the future. The fix is in svn and will go into the next release.
As well as the pending 3.0.0.CR2 release, I have released and synchronised to Maven central releases 1.9.1 and 2.0.1 which also contain the fix you recommended. This makes available releases with the necessary fix to LocalDate and YearMonthDay types for existing stable versions for both current and previous versions of Hibernate.
Thanks Chris for the quick fix. I will test if it works today.
Is it possible to use those Joda types with embeddables?
I have problems using the type LocalDate for a field in an @Embeddable component. This component is @Embedded in an entity. The insert operation fails (org.hibernate.exception.DataException: Data truncation: Incorrect date value: '’' for column 'postingDate' at row 1) and it seems the object of LocalDate is converted to a binary representation.
Maz,
This definitely should be possible. Can you share a bit more information about your use case (such as a test that can reproduce and some details of the database etc) and I will try to assist.
I am also very stuck with embedding Joda types. The following was tried with 3.0.0.CR1 and all combinations of Hibernate 4.0.1/4.1.0, joda-time 2.0/2.1, joda-money 0.6, LocalDate/CurrencyUnit. Other environment details. java 6 se, spring 3.1.1, spring-data-jpa 1.0.3, sqlserver2008
Code shortened and genericised:
@Embeddable public class DateThing {
LocalDate value;
}
@Entity public class Parent {
@Id private int id;
@Embedded private DateThing myDate;
}
On inserting a new Parent, I get the following:
2012-04-25 12:44:14,240 2188 ERROR [SqlExceptionHelper.java: 144] (main:) Implicit conversion from data type varbinary to date is not allowed. Use the CONVERT function to run this query.
Looking at the SQL profile, Hibernate is treating "parent.myDate.value" as an Object and trying to serialise it into the target column. This also fails when using multiple embeddables and @AttributeOverrides
The non-embedded case works perfectly (i.e. usertype is registered correctly). Using java.util.Date works (i.e. @Embeddable is working, generally speaking)
@Embeddablepublic class Balance implements Serializable {
// auto registration fails with embeddables -> manually adding the type will work
@org.hibernate.annotations.Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
private LocalDate postingDate;
//...
}
That's almost great, thanks so much! I have one rather killer flaw though. My actual implementation looks more like this:
@Embeddable public class Thing<X> {
X value;
}
@Entity public class Parent {
@Id private int id;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "value", column = @Column(name = "MyCurrency"))
})
private Thing<LocalDate> myDate;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "value", column = @Column(name = "MyValue"))
})
private Thing<Double> myDate;
...
}
There is no place where I can add that @Type annotation because X is inferred from the Generic signature.
For the failure to register automatically for fields within embeddables I have created HHH-7310 and will be making a pull request for the fix soon.
Thanks Chris
Superb - HHH-7310 is now fixed. @Embedded Joda types now work out-of-the-box with hibernate-core 4.1.5.FINAL
thanks, Marc
First, thanks for this superb library. It's been a breeze to setup Joda Time Hibernate mappings. One question though: Any reason, why PersistentLocalDateTime is not included with the autoregistered types?
Thanks for the feedback. I've added autoregistration of PersistentLocalDateTime as per the suggestion - it will be available from 3.0.0.CR3 onwards.
Is it possible Usertype project support Spring Data MongoDB?
I use Spring Data JPA in a project meanwile using Spring Data MongoDB. Since Usertype support Hibernate so Spring Data JPA is well supported by Usertype. but for Spring Data MongoDB we need re-implement all the conversion logic for joda-time and joda-money.
Spring has lots of Spring Data projects to integrate persistent layer with spring framework, hope UserType can unify the mapping between Java Object and Persisitent Layer.
hi,
I've been using your library for several years now, great work! I have a question regarding 3.0.0.GA, though: why are you doing
System.err.println(value.toString());
in org.jadira.usertype.dateandtime.joda.columnmapper.StringColumnDateTimeZoneWithOffsetMapper?
It spams the logs a lot in my case.
Thank you.