Hibernate: one-to-one mapping is not working correctly

1.3k views Asked by At

I am using Hibernate framework in my Spring web application for working with Oracle database.

I have these 2 entities with mutual relationship: pseudo ERD diagram

Basically, each Person can have exactly zero or one User and User must have exactly one Person.

I want to achieve a behaviour that when I select some User from database I get Person entity mapped to it.

Here are my POJOs:

public class User implements Serializable {

    private String id = null;
    private String username = null;
    private String password = null;
    private boolean enabled = false;
    private Person person = null;
    private LocalDateTime created = null;

    // getters and setters
}

public class Person implements Serializable {

    private String id = null;
    private String firstName = null;
    private String lastName = null;

    // getters and setters
}

and here are corresponding configuration xml files:

<hibernate-mapping package="webapp.models">
    <class name="webapp.models.User"
           table="USERS">

        <id name="id"
            type="java.lang.String">
            <column name="ID"
                    not-null="true"
                    unique="true"/>
            <generator class="guid"/>
        </id>

        <property name="username"
                  type="java.lang.String">
            <column name="USERNAME"
                    not-null="false"
                    unique="false"/>
        </property>

        <property name="password"
                  type="java.lang.String">
            <column name="PASSWORD"
                    not-null="false"
                    unique="false"/>
        </property>

        <property name="enabled"
                  type="java.lang.Boolean">
            <column name="ENABLED"
                    not-null="false"
                    unique="false"/>
        </property>

        <property name="created"
                  type="webapp.utils.hibernate.LocalDateTimeUserType">
            <column name="CREATED"
                    not-null="false"
                    unique="false"/>
        </property>

        <one-to-one name="person"
                    class="Person"
                    fetch="select"
                    lazy="false">
        </one-to-one>
    </class>
</hibernate-mapping>

<hibernate-mapping package="webapp.models">
    <class name="webapp.models.Person"
           table="PERSONS">

        <id name="id"
            type="java.lang.String">
            <column name="ID"
                    not-null="true"
                    unique="true"/>
            <generator class="guid"/>    
        </id>

        <property name="firstName"
                  type="java.lang.String">
            <column name="FIRST_NAME"
                    not-null="false"
                    unique="false"/>
        </property>

        <property name="lastName"
                  type="java.lang.String">
            <column name="LAST_NAME"
                    not-null="false"
                    unique="false"/>
        </property>

        <property name="created"
                  type="webapp.utils.hibernate.LocalDateTimeUserType">
            <column name="CREATED"
                    not-null="false"
                    unique="false"/>
        </property>
    </class>
</hibernate-mapping>

My problem is that the person property in user is always set to null even though corresponding Persons exist.

Here is the execution code:

public Collection<User> getAll() {
    Session session = null;
    try {
        session = _sessionFactory.openSession();
        Query query = session.createQuery("from User fetch all properties");
        List<User> collection = query.list();
        return Collections.unmodifiableCollection(collection);
    } catch (HibernateException hbEx) {
        return null;
    } finally {
        if (session != null && session.isOpen())
            session.close();
    }
}

I turned on Hibernate logging with SQL queries and bindings and I found out that when it selects a Person from database, it uses query like this:

select
    person0_.ID as ID1_0_0_,
    person0_.FIRST_NAME as FIRST_NAME2_0_0_,
    person0_.LAST_NAME as LAST_NAME3_0_0_,
    person0_.CREATED as CREATED4_0_0_ 
from
    PERSONS person0_ 
where
    person0_.ID=?

and in WHERE clause sets person0_.ID as ID of the User, so it doesn't take PERSON_ID foreign key in Users table.

Am I setting something wrong or where could be the problem?

Thanks in advance for any help.

1

There are 1 answers

1
Puneet Pandey On

one-to-one relationship must ensure both entities are assigned the same primary key. you should declare special foreign identifier generator which will get the primary key value from another table when constrained=”true”.

    <id name="id" type="java.lang.Integer">
        <column name="id" />
        <generator class="foreign">
            <param name="property">person</param>
        </generator>
    </id>