views:

293

answers:

3

I want to persist my litte zoo with Hibernate:

@Entity
@Table(name = "zoo") 
public class Zoo {
    @OneToMany
    private Set<Animal> animals = new HashSet<Animal>();
}

// Just a marker interface
public interface Animal {
}

@Entity
@Table(name = "dog")
public class Dog implements Animal {
    // ID and other properties
}

@Entity
@Table(name = "cat")
public class Cat implements Animal {
    // ID and other properties
}

When I try to persist the zoo, Hibernate complains:

Use of @OneToMany or @ManyToMany targeting an unmapped class: blubb.Zoo.animals[blubb.Animal]

I know about the targetEntity-property of @OneToMany but that would mean, only Dogs OR Cats can live in my zoo.

Is there any way to persist a collection of an interface, which has several implementations, with Hibernate?

A: 

I can guess that what you want is mapping of inheritance tree. @Inheritance annotation is the way to go. I don't know if it will work with interfaces, but it will definitely work with abstract classes.

Ivan Yatskevich
I'll try that and if it doesn't work I'll go for abstract classes.
Olvagor
Yep, abstract class is a better solution. As Péter Török has already said, you can put the id and other common properties to the Animal class.
Ivan Yatskevich
+3  A: 

JPA annotations are not supported on interfaces. From Java Persistence with Hibernate (p.210):

Note that the JPA specification doesn’t support any mapping annotation on an interface! This will be resolved in a future version of the specification; when you read this book, it will probably be possible with Hibernate Annotations.

A possible solution would be to use an abstract Entity with a TABLE_PER_CLASS inheritance strategy (because you can't use a mapped superclass - which is not an entity - in associations). Something like this:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class AbstractAnimal {
    @Id @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;
    ...
}

@Entity
public class Lion extends AbstractAnimal implements Animal {
    ...
}

@Entity
public class Tiger extends AbstractAnimal implements Animal {
    ...
}

@Entity
public class Zoo {
    @Id @GeneratedValue
    private Long id;

    @OneToMany(targetEntity = AbstractAnimal.class)
    private Set<Animal> animals = new HashSet<Animal>();

    ...
}

But there is not much advantages in keeping the interface IMO (and actually, I think persistent classes should be concrete).

References

Pascal Thivent
Truth is, my real problem is a bit more complex than the question above so your answer doesn't work in my case. But it looks like a correct answer to my question so I'll accept it. Thanks!
Olvagor
A: 

hey !! i think u have to annotate the interface too with @Entity and we have to annotate @Transient on all getters and setters of interface............... and it gets stored. i solved the problem recently

sammy