Search code examples
javahibernatejodatimeperiodusertype

Jodatime Period to Jadira Usertype PersistentPeriodAsString. Giving custom format?


I need to store delta time I'm receiving in the format: yyyy-MM-ddTHH:mm in database. For that I'm using Joda-Time Period class. Now, I've to do the mapping from Period to DB column. I'm using Hibernate Framework, and found out Jadira UserType project. Sounds good. Here's what I've got till now:

@Entity
class SomeEntity {
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentPeriodAsString")
    private Period deltaTime;
}

But the issue is, it has a specific format - PnYnMnDTnHnMnS, as I guess it uses AbstractPeriod#toString() method.

How can I alter it to use the one argument AbstractPeriod#toString(PeriodFormatter) passing my own PeriodFormatter, to store it in the yyyy-MM-ddTHH:mm format?

Earlier I faced this issue with JPA and EclipseLink, and I solved it using EclipseLink Converter, but haven't found a way till yet to resolve this. Any inputs?


Solution

  • You could implement your own type. To do that, you can mirror the definition of PersistentPeriodAsString by extending AbstractSingleColumnUserType and providing your own ColumnMapper:

    public class PersistentPeriodAsFormattedString extends
            AbstractSingleColumnUserType<Period, String,
                StringColumnPeriodFormatterMapper> {
    }
    
    public class StringColumnPeriodFormatterMapper extends
            AbstractStringColumnMapper<Period> {
        private static final PeriodFormatter FORMATTER = ...;
    
        @Override
        public Period fromNonNullValue(String s) {
            return FORMATTER.parsePeriod(s);
        }
    
        @Override
        public String toNonNullValue(Period value) {
            return value.toString(FORMATTER);
        }
    }
    

    Note that for any UserType the following must be true (Hibernate Javadoc):

    Implementors must be immutable and must declare a public default constructor.
    

    Similarly, the ColumnMapper used by AbstractSingleColumnUserType must define a public default constructor as an instance is instantiated by reflections:

    columnMapper = (C) TypeHelper
        .getTypeArguments(AbstractSingleColumnUserType.class, getClass()).get(2)
        .newInstance();