Search code examples
javahibernatejpahibernate-mappinggenerics

How to annotate hibernate collections with generic types?


I have a one-to-many class member of type List< GenericType < T > >. What is the recommended way to annotate this member in Hibernate?

Morbid details:

@Entity
public class DvOrdered extends DataValue
{
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name="dv_ordered_other_reference_ranges", 
        joinColumns = @JoinColumn(name = "reference_range_id"),
        inverseJoinColumns = @JoinColumn(name = "dv_ordered_id"))
    private List<ReferenceRange<T>> otherReferenceRanges;
}

I get

Caused by: org.hibernate.AnnotationException: Property com.safehis.ehr.rm.datatypes.quantity.DvOrdered.otherReferenceRanges has an unbound type and no explicit target entity. Resolve this Generic usage issue or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type
at org.hibernate.cfg.PropertyContainer.assertTypesAreResolvable(PropertyContainer.java:140)
at org.hibernate.cfg.PropertyContainer.getProperties(PropertyContainer.java:118)
at org.hibernate.cfg.AnnotationBinder.addElementsOfClass(AnnotationBinder.java:1554)
at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:236)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:775)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3845)
at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3799)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1412)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)

Thanks in advance for any reply.


Solution

  • The generic information is lost at compile-time due, to type erasure so Hibernate can't figure out what type T is in your case.

    You can change your code to this:

    private List<ReferenceRange<T>> otherReferenceRanges;
    

    And then use inheritance so that each ReferenceRange subclass embeds a certain type.

    public abstract class ReferenceRange<T> {
    
        public abstract T getReference();
    }
    
    public class IntegerReferenceRange extends ReferenceRange<Integer> {
    
        private Integer reference;
    
        @Override
        public Integer getReference() {
            return reference;
        }
    }