Search code examples
javahibernatemergehibernate-mappingmany-to-one

Hibernate does not initialize many-to-one relation after merge


I have the following class:

public class Entry{
    private long cardNumber;
    private long companyId;
    private Company company;
    private Long id;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public long getCardNumber() {
        return mediaSerialNumberId;
    }
    public void setCardNumber(long number) {
        this.cardNumber = number;
    }
    public long getCompanyId() {
        return companyId;
    }
    public void setCompanyId(long id) {
        this.companyId = id;
    }
    public Company getCompany() {
        return company;
    }
    public void setCompany(Company company) {
        this.company = company;
    }
}

With the following uni-directional mapping to a Company:

<hibernate-mapping>
   <class name="foo.bar.Entry" table="RECONSTRUCTION" polymorphism="implicit" lazy="false">
       <id name="id" column="ID" type="long" unsaved-value="null">
           <generator class="sequence">
               <param name="sequence">SEQ_ENTRY</param>
           </generator>
       </id>
       <property name="cardNumber" column="CARDNUMBER" type="long"/>
       <property name="companyId" column="COMPANYID" type="long"/>
       <many-to-one name="company" column="COMPANYID" class="foo.bar.Company" insert="false" update="false" />
   </class>
</hibernate-mapping>

I create a new Entry,set CardNumber=123, CompanyId=3 and and save it with session.merge(). The Company with ID=3 exists, I can load it with session.load(). The Company does not have any Hibernate-relation back to Entry.

The returned persisted Entry has getCompanyId()==3 but getCompany()==null.

Why isn't the many-to-one relation initialized by Hibernate in the newly persisted object? If I switch so that the "companyId" attribute is insert/update=false, I can set an existing Company object instead, but then the getCompanyId()==null instead of the ID of the Company.

In the database the COMPANYID column is correctly saved.

I am using Hibernate 3.6.10.


Solution

  • You need to refresh the entity:

    Entry entry = new Entry();
    entry.setCardNumber(123);
    entry.setCompanyId(3);
    entry = session.merge(entry);   
    
    session.flush();
    session.refresh(entry );
    

    Because the merge copies the given entity state over the one fetched from the database, the null many-to-one association will also be copied over the one fetched from the database. A refresh should solve it.

    A better approach is to simply use the many-to-one association without the extra companyId column:

    <many-to-one name="company" column="COMPANYID" class="foo.bar.Company"/>
    

    This way, you can even set the company without having to fetch it from DB:

    Entry entry = new Entry();
    entry.setCardNumber(123);
    
    entry.setCompany(new Company());
    entry.getCompany().setId(3);
    session.persist(session);