Java – hibernate – spring/bean mapping set

hibernatejavamappingspring

I'm pretty much a newb with spring-hibernate and I have been trying to make it work.

I have a data model like this:

patient                prescription
----------             --------------
patient_id*            prescription_id*
first_name             patient_id*
last_name              date
...

I'm using spring beans with hibernate template to define my session/hibernatetemplate and dao like this:

    <bean id="mySessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource" />
    <property name="mappingResources">
        <list>
            <value>./org/example/smartgwt/shared/model/prescription.hbm.xml</value>
            <value>./org/example/smartgwt/shared/model/patient.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>hibernate.dialect=org.hibernate.dialect.HSQLDialect</value>
    </property>
</bean>

<!-- Wrapper for low-level data accessing and manipulation -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="mySessionFactory" />
    </property>
</bean>

<!--  -->

<bean id="patientDao" class="org.example.smartgwt.server.data.PatientDao">
    <property name="hibernateTemplate">
        <ref bean="hibernateTemplate" />
    </property>
</bean>

<bean id="prescriptionDao" class="org.example.smartgwt.server.data.PrescriptionDao">
    <property name="hibernateTemplate">
        <ref bean="hibernateTemplate" />
    </property>
</bean>

For a while I had only patient table and all was ok. But then I decided to add a prescription which uses a foreign key of type patient_id. Basically I have 2 POJO model objects like this:

public class Patient implements Serializable {

///////////////////////////////////////////////////////////////////////////
// Data members
///////////////////////////////////////////////////////////////////////////
private static final long serialVersionUID = 1L;
private int    patientId;
private String firstName;
private String lastName;
private Date   birthDate;
private String address;
private String phone;

private Set patientPrescriptions;

public Patient() {}

public void setPatientId(int patientId) {
    this.patientId = patientId;
}

public int getPatientId() {
    return patientId;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getFirstName() {
    return firstName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public String getLastName() {
    return lastName;
}

public void setBirthDate(Date birthDate) {
    this.birthDate = birthDate;
}

public Date getBirthDate() {
    return birthDate;
}

public void setAddress(String address) {
    this.address = address;
}

public String getAddress() {
    return address;
}

public void setPhone(String phone) {
    this.phone = phone;
}

public String getPhone() {
    return phone;
}

public void setPatientPrescriptions(Set patientPrescriptions) {
    this.patientPrescriptions = patientPrescriptions;
}

public Set getPatientPrescriptions() {
    return patientPrescriptions;
}
}

(Similar simpler thing for Prescription).

The thing that is bugging me is the private Set patientPrescriptions member. Here is my hbm.xml mapping for my patient class.

<hibernate-mapping>
<class name="org.example.smartgwt.shared.model.Patient" table="patient" lazy="true">
    <id name="patientId" column="patient_id">
        <generator class="increment"/>
    </id>

    <property name="firstName">
        <column name="first_name"/>
    </property>
    <property name="lastName">
        <column name="last_name"/>
    </property>
    <property name="birthDate">
        <column name="birth_date"/>
    </property>
    <property name="address">
        <column name="address"/>
    </property>
    <property name="phone">
        <column name="phone"/>
    </property>

    <set name="patientPrescriptions" cascade="all">
        <key column="patient_id"/>
        <one-to-many class="Prescription"/>
    </set>

</class>

As soon as I reference that in my patient.hbm.xml mapping file I get an error.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'prescriptionDao' defined in file [C:\eclipse\workspace\smart-gwt\WebContent\WEB-INF\resources\hibernate-beans.xml]: Cannot resolve reference to bean 'hibernateTemplate' while setting bean property 'hibernateTemplate'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateTemplate' defined in file [C:\eclipse\workspace\smart-gwt\WebContent\WEB-INF\resources\hibernate-beans.xml]: Cannot resolve reference to bean 'mySessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mySessionFactory' defined in file [C:\eclipse\workspace\smart-gwt\WebContent\WEB-INF\resources\hibernate-beans.xml]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: Prescription

Why do I get the unmapped error for this Set? If I remove that from my hbm.xml, I can do pretty my everything with my session. Is there something special to do while requesting the dao object? Here is the code I use to get my dao.

        Resource resource = new FileSystemResource("./hibernate-beans.xml");
        BeanFactory factory = new XmlBeanFactory(resource);
        PrescriptionDao prescriptionDao = (PrescriptionDao)factory.getBean("prescriptionDao");
        PatientDao clientDao = (PatientDao) factory.getBean("patientDao");

Thank you

Best Answer

Well the obvious answer is that your hibernate mapping makes no mention of the Prescription class, so Hibernate doesn't know what to do with it.

Assuming that's not the case, and that instead you just didn't show us the mapping, then the next most obvious answer is this:

<one-to-many class="Prescription"/>

The class attribute should be a fully-qualified class name, which Prescription isn't. Maybe it should be something like:

<one-to-many class="org.example.smartgwt.shared.model.Prescription"/>