Hi everyone! (it's my first post on hibernate forum)
At the beginning I would inform that I am hibernate newbie, so your patience is very appreciated.
My question refers to mapping the following class hierarchy:
(the following code is complete and ready to run if you wish to try it in your IDE)
Code:
package pl.edu.uj.spring.hibernate.collections;
public interface Identifiable {
    Long getId();
}
Identifiable interface allows to retrieve primary key of an object (used when working with DB). Please notice that there is no setter here. I don't want to make possible changing this value from Java code. ID (key) should be set ones, and stay the same up to removing object. As far as I know in fact many DB vendors do not allow to update primary key of an entity. 
Code:
package pl.edu.uj.spring.hibernate.collections;
public interface Person extends Identifiable {
    public String getName();
    public String getSurname();
    public void setName(String name);
    public void setSurname(String surname);
}
Code:
package pl.edu.uj.spring.hibernate.collections;
public class Student implements Person {
    private Long id;
    private String name;
    private String surname;
    private int classNumber;
    public Student(String name, String surname, int classNumber) {
        setName(name);
        setSurname(surname);
        setClassNumber(classNumber);
    }
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public String getSurname() {
        return surname;
    }
    public int getClassNumber() {
        return classNumber;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setSurname(String surname) {
        this.surname = surname;
    }
    public void setClassNumber(int classNumber) {
        this.classNumber = classNumber;
    }
}
Code:
package pl.edu.uj.spring.hibernate.collections;
public class Teacher implements Person {
    private Long id;
    private String name;
    private String surname;
    private String specializationSubject;
    public Teacher(String name, String surname, String specializationSubject) {
        setName(name);
        setSurname(surname);
        setSpecializationSubject(specializationSubject);
    }
    public Long getId() {
        return id;
    }
    public String getName() {
        return name;
    }
    public String getSurname() {
        return surname;
    }
    public String getSpecializationSubject() {
        return specializationSubject;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setSurname(String surname) {
        this.surname = surname;
    }
    public void setSpecializationSubject(String specializationSubject) {
        this.specializationSubject = specializationSubject;
    }
}
Please notice that persons collections uses interface as a generic type! Classes Teacher and Student implements this interface:
Code:
package pl.edu.uj.spring.hibernate.collections;
import java.util.List;
public class School implements Identifiable {
    private Long id;
    private List<Person> persons;
    public Long getId() {
        return id;
    }
    public void setPersons(List<Person> persons) {
        this.persons = persons;
    }
    public List<Person> getPersons(List<Person> persons) {
        return persons;
    }
    public void addPerson(Person person) {
        persons.add(person);
    }
}
Here is how this everything is used (Spring + Hibernate):
Code:
package pl.edu.uj.spring.hibernate.collections;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class SchoolDAO extends HibernateDaoSupport {
    public void persist(School school) {
        getHibernateTemplate().save(school);
    }
    public School load(Long id) {
        return getHibernateTemplate().load(School.class, id);        
    }
}
Code:
public class HibernateCollections {
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<Person>();
        persons.add(new Teacher("John","Smith","History"));
        persons.add(new Teacher("Michael","Black","Biology"));
        persons.add(new Student("Wladimir","Vodka", 3));
        persons.add(new Student("Marko","Ramirez",4));
        School school = new School();
        school.setPersons(persons);
        ApplicationContext ctx = new ClassPathXmlApplicationContext("pl/edu/uj/spring/hibernate/collections/context.xml");
        SchoolDAO dao = ctx.getBean("schoolDao", SchoolDAO.class);
        dao.persist(school);
    }
}
(I know that I can simplify this code by using inheritance but I just wanted to flash on collection persisting)
Ok so my question is how to map everything in xml file?
I've tried in this way (using inheritance - classes Teacher and Student implements interface Person):
Code:
<?xml version="1.0" ?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"  >
<hibernate-mapping>
    <class name="pl.edu.uj.spring.hibernate.collections.School" table="SCHOOLS">
        <id name="id" column="ID" access="field">
            <generator class="sequence">
                <param name="sequence">HIBERNATE_SCHOOLSEQ</param>
            </generator>
        </id>
        <!--
                        http://docs.jboss.org/hibernate/stable/core/reference/en/html/associations.html
                        one - to - many
                  -->
        <bag name="persons" table="School2Person">
            <key column="schoolId"/>
            <many-to-many column="personId" unique="true" class="pl.edu.uj.spring.hibernate.collections.Person"/>
        </bag>
    </class>
    <class name="pl.edu.uj.spring.hibernate.collections.Person" abstract="true">
        <id name="id" column="ID" access="field">
            <generator class="sequence">
                <param name="sequence">HIBERNATE_PERSONSEQ</param>
            </generator>
        </id>
        <joined-subclass name="pl.edu.uj.spring.hibernate.collections.Student" table="STUDENTS">
            <key column="ID"/>
            <!--
     <id name="id" column="ID" access="field">
         <generator class="sequence">
             <param name="sequence">HIBERNATE_STUDENTSEQ</param>
         </generator>
     </id>       -->
            <property name="name" column="NAME"/>
            <property name="surname" column="SURNAME"/>
            <property name="classNumber" column="CLASS_NUMBER"/>
        </joined-subclass>
        <joined-subclass name="pl.edu.uj.spring.hibernate.collections.Teacher" table="TEACHERS">
            <key column="id"/>
            <!--
            <id name="id" column="ID" access="field">
                <generator class="sequence">
                    <param name="sequence">HIBERNATE_TEACHERSEQ</param>
                </generator>
            </id>
            -->
            <property name="name" column="NAME"/>
            <property name="surname" column="SURNAME"/>
            <property name="specializationSubject" column="SPECIALIZATION_SUBJECT"/>
        </joined-subclass>
    </class>
</hibernate-mapping>
But it results in exception:
Quote:
org.hibernate.PropertyNotFoundException: field [id] not found on pl.edu.uj.spring.hibernate.collections.Person
... and he's right. But I do not want to add this field to interface (it would become public static final...). When working with classes I could do  
<id name="id" column="ID" access="field"> but it's impossible with interfaces.
Is there any way to map this?
I would also ask question to Hibernate experienced developers if it is shame using classes all the time instead interfaces? I know that in regular Java programming we should program to interfaces but I found out that it is sometimes extremely complicated to map it in hibernate (like in the preceding example). As I can see in many open source projects built on Hibernate, programmers in domain tier do not use interfaces (almost) at all - only classes - how about you? In my opinion (but as I said I am newbie) it is far more complicated to make it work with hibernate when using interfaces than using only classes and make some refactoring when needed.
Thank you in advance!
Piotr