views:

202

answers:

3

Ok, this question is best explained in code. So will try to present the most succinct example I can.

Timestamped.java

@Embeddable
public class Timestamped<E> {
    private E value;
    private Date timestamp;
    ...
}

Foo.java

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE")
public class Foo {
    @Embedded
    @AttributeOverides({
        @AttributeOverride(name="timestamp", column=@Column("VALUE_TS")),
        @AttributeOverride(name="value",     column=@Column("VALUE"))
    })
    private TimestampedValue<E> value;
    ...
}

Bar.java

@Entity
@DiscriminatorValue("BAR")
public class Bar extends Foo<Double> { }

What I need is for Bar to use the appropriate type converter for value.value and a different converter for each subclass of Foo. Ideally I would just like to augment this code, but I would be OK making Foo abstract and moving the value field to each of the subclasses with additional annotations.

+1  A: 

The first approach is not going to work - you can't persist "genericized" classes.

You will either have to move value into concrete subclasses like you've suggested OR write a UserType to persist your Timestamped component.

ChssPly76
If I move the value field, how do I set the type of a component field. Is there some sort of component field over writing equivalent of @Type?
Ambience
You'd have to declare it as a concrete type - e.g. `private TimestampedValue<Double>` and use `@AttributeOverrides`. Hibernate can't deal with generics - at all, so all classes you persist / annotate have to explicitly declare type parameter (or be non-generic). If you hierarchy is big, writing custom UserType may be a better approach.
ChssPly76
I ended up using ChssPly76's answer. So foo now has a "TimestampedValue<Double> value" field.
Ambience
A: 

If what you're trying to do is make many classes that correspond to many tables but use the same column names for the 'timestamp' and 'value' properties, then what you want is a 'mapped superclass' with those columns, not an embedded class. Research the @MappedSuperclass annotation.

Jherico
I think I would run into a similar problem if I flattened the fields out. But I would very much like to keep it a component as several fields on the object may have a timestamp and associated user.
Ambience
You can use mapped superclasses for embeddables as well.
Jherico
A: 

You are running into an erasure problem. Hibernate cannot know what to do with the generic types, because that information is not available at runtime. It would be nice though.

Nathan Feger