Using hibernate with generics

18,441

Solution 1

What you're looking for is probably Hibernate's implicit polymorphism. There's also a little-known "any" relationship which gives complete flexibility, but it has its tradeoffs. You can also use an "any" in a many-to-any.

Edit: I've created a runnable example on Github based around your "Box" class and using an @Any mapping. You can browse it (or the Box class specifically) or check it out and run it with

git clone git://github.com/zzantozz/testbed tmp
cd tmp
mvn -q compile exec:java -Dexec.mainClass=rds.hibernate.AnyMapping -pl hibernate-any

Solution 2

I've already done that but with subclasses.

Your generic class must be abstract and subclasses must define the generic parameter

Share:
18,441
Ryan
Author by

Ryan

Updated on June 01, 2022

Comments

  • Ryan
    Ryan almost 2 years

    I am having some trouble understanding how Hibernate deals with generics and was wondering the best way to accomplish my goal.

    Given a simple generic entity:

    @Entity
    public class Box<T>{
    
      private T t;    
      @Id
      private long id;
    
      public void setT(T t) {
          this.t = t;
      }
    
      public T getT() {
          return t;
      }
    
      public void setId(long id) {
          this.id = id;
      }
    
      public long getId() {
          return id;
      }
    }
    

    When going through hibernate initialization, I am getting the exception: ...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

    I am nearly certain this is because I haven't given hibernate a list of restrictions of what <T> can actually be. I know you can specify things such as targetEntity=String.class above t in an annotation, but then you lose the flexibility of having generics. Can I limit the scope of what is an acceptable generic using annotations? For instance: What if I want classes ChildA, ChildB, whom inherit from an abstract class Parent to be persistable there. In addition, it should also be able to accept Strings. Can Hibernate deal with such a thing?

  • Ryan
    Ryan almost 13 years
    I understand that part, but what about an object type such as String that has nothing to do with that inheritance tree. Is that possible to specify additionally?
  • Jerome Cance
    Jerome Cance almost 13 years
    what I want to say is that you can specify generic only if the class which has generic definition is not saved in database as hibernate doesn't know what to save. You can use the targetEntity field to specialize that
  • Ryan
    Ryan almost 13 years
    Ryan, is there anywhere online that has a reference to using this type of mapping using generics? I believe have a found a description of what you are referring to here: v4forums.wordpress.com/2008/12/27/… however that example does not seem to satisfy what I want to do. Are you saying I can annotate my generic fields with @any(xxx) with the classes that may be used?
  • Ryan Stewart
    Ryan Stewart almost 13 years
    I should've directed you to the newer 3.6 docs. They have more detail. I updated my answer with that link and with a runnable example.
  • Ryan
    Ryan over 12 years
    Thank you very much for going through this. Excellent explanation and answer.
  • Ryan
    Ryan over 12 years
    Ryan: How would this change if Box also needed a List of <T>'s as well as an object of T?
  • Ryan Stewart
    Ryan Stewart over 12 years
    I've never needed or stumbled upon a way to do that. I'm not sure if it's possible. There's an _@Any and a _@ManyToAny, but no _@OneToAny. The complexity of such a mapping might have prevented anyone from ever implementing it. If you think about it--ignoring the generic type constraint as Hibernate would--the content of such a collection could consist of an unlimited number of different types, each specified by a discriminator that would have to live somewhere. It would definitely have to be a relationship using a join table because that's where the discriminators would have to live.
  • Ryan Stewart
    Ryan Stewart over 12 years
    Then, in order to load the collection, you'd have to execute a query for each row in the join table, or best case, a query for each distinct discriminator. The results of all such queries would then be aggregated into the collection. See what I meant by complex? I just don't think you're going to find this feature. It feels too expensive and too complicated.
  • Ganesh Satpute
    Ganesh Satpute about 5 years
    @RyanStewart when I run it I'm getting similar error Foreign key (FKq8tn93chnsr2x9om5wd0vfma6:output [referenced_entity_type,referenced_entity_id])) must have same number of columns as the referenced primary key (stack [id]). What am I missing?