views:

230

answers:

3

I have a property field in a class that is of type javax.xml.datatype.Duration. It basically represents a time span (e.g. 4 hours and 34 minutes).

JPA is telling me it is an invalid type, which doesn't shock me.

Whats a good solution this? I could implement my own Duration class, but I don't know how to get JPA to "accept" it as a datatype.

+1  A: 

You can mirror the exact fields in the Duration class into your own custom class, but that might be overkill...I'm assuming you don't need that kind of duration flexibility/granularity.

So pick the fields you want, add them to your class, mark the class with the @Embeddable annotation, and add the proper JPA annotations to the fields (which I'm assuming will be simple ints).

In your entity that will store a duration, add the @Embedded annotation to the field or getter, whichever you typically use. From here you can further tweak the column definitions with @AttributeOverride.

Jeff
Are you saying to wrap the Duration class or implement a new one from scratch?
HDave
Creating your own from scratch would be easiest. The javax.xml.datatype.Duration class has more fields then you probably want to expose as columns in your DB table, so create a custom Duration object with just the time granularity that you need.
Jeff
+2  A: 

Whats a good solution this? I could implement my own Duration class, but I don't know how to get JPA to "accept" it as a datatype.

JPA does not support custom types so if you want to go this way you'll have to use a JPA extension from your provider. For example, Hibernate allows to define custom value types that you declare with @Type. Obviously, this will harm portability between providers which might be a concern. If not, then you know it is doable.

With standard JPA, the traditional approach would be to add another getter/setter pair which adapt the problematic property and perform conversion when accessed. I would use a Long to store a duration:

public MyEntity implements Serializable {
    private Long id;
    private javax.xml.datatype.Duration duration;

    @Id
    @GeneratedValue
    public Long getId() {
        return this.id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    @Transient
    public Duration getDuration() {
        return this.duration;
    }
    public void setDuration(Duration duration) {
        this.duration = duration;
    }

    public Long getDurationAsJpaCompatibleType() {
        return MyXmlUtil.convertDurationToLong(this.duration);
    }
    public void setDurationAsJpaCompatibleType(Long duration) {
        setDuration(MyXmlUtil.convertLongToDuration(duration));
    }
}
Pascal Thivent
+1  A: 

You could try joda-time hibernate. Refer to the available types that can be persisted. You could then use the joda Duration in the following way:

@Type(type="org.joda.time.contrib.hibernate.PersistentDuration")
private Duration startDateTime;
Kariem