I have the exact same thing with my model in terms of having an interface that has a function that returns a generic collection of the same type as the interface. I first tried using annotations, and that got me along up until a certain point. That point was the fact that annotations will work, but if your class extends any classes that are Serializable, then the Hibernate parser (?) will try to continue to look for annotations in those classes as well. This is just not realistic because what if you decide to extend a class that you personally did not write? You cannot just add an @Transient tag to anything that you want. I posted a similar topic about this, and Emmanuel told me that this issue will be resolved in the next EJB3 draft (whenever that is). I personally cannot wait that long, so I have resorted to using XML mapping. When it is implemented in the draft, I will go back and change my code simply because if you add one interface / class, you must also add the corresponding XML mapping for it. Having everything in one place just makes refactoring much easier.
As for XDoclet, I can't help you there. I am pretty new to Hibernate, and trying to throw out any suggestions regarding that would be like throwing poo at the wall and see if it sticks.
Anyway, here's how I setup my interface / class structure: (using your "Animal" naming convention)
Code:
public interface Animal extends Serializable {
Integer getId();
void setId(Integer value);
public List<Animal> getChildren();
public void setChildren(List<Animal> children);
public Animal getParent();
public void setParent(Animal parent);
public void addChild(Animal child); // My function return a "boolean" because I use a Set instead of a List
...
}
Quote:
I really can't use abstract classes in this case because in my actual application I have classes which implement multiple interfaces and they cannot reasonably get transformed into a single "extends" statement.
Hopefully there may be a workaround for this. What I did was have an AbstractAnimal that just implements the getId() / setId() functionality, and then have a ChildAnimal and ParentAnimal that implement the rest of the functions above (granted a ChildAnimal cannot have chlidren...in my application I had to logically stop it somewhere).
As for my mapping, it's something of the following:
(Animal.hbm.xml -- Covers both the Animal interface and AbstractAnimal class)
Code:
...
<hibernate-mapping>
<class name="a.b.c.Animal" table="Animal" lazy="false">
<id name="id" column="ANIMAL_ID">
<generator class="native"/>
</id>
<joined-subclass name="a.b.c.AbstractAnimal" extends "a.b.c.Animal" lazy="false">
<key column="ANIMAL_ID"/>
</joined-subclass>
</class>
</hibernate-mapping>
(ChildAnimal.hbm.xml)
Code:
...
<joined-subclass name="a.b.c.ChildAnimal" extends="a.b.c.AbstractAnimal" lazy="false">
<key column="ANIMAL_ID"/>
</joined-subclass>
(ParentAnimal.hbm.xml)
Code:
...
<joined-sublcass name="a.b.c.ParentAnimal" extends="a.b.c.AbstractAnimal" lazy="false">
<key column="ANIMAL_ID"/>
<set name="children">
<key column="parent_id"/>
<one-to-many class="a.b.c.Animal"/>
</set>
</joined-subclass>
For my model, a given child can only have one parent, but one parent can have many children. I am not sure if you are doing a many-to-many relationship, but if you are, I can't help you there. My model may be slightly confusing and some parts may be unnecessary for your application, but hopefully this should point you in the right direction.