Sanjay Jain
Sanjay Jain

Reputation: 3587

JPA | One to one mapping with eager fetch

I am working with a JPA sample application with hibernate as JPA provider. In which I am having a one to one mapping with fetch type EAGER.

Here below is my code block:

Person.java

public class Person extends Persistent  implements Serializable {

private static final long serialVersionUID = 1L;

String name;

// address as composition
Address address;

String addressId;

Address.java

public class Address extends Persistent implements Serializable {


private static final long serialVersionUID = 1L;


String address;

mapping.xml

<entity name="Person" class="com.csam.mtp.wallet.wallet.Person"
    access="FIELD">
    <table name="person" />
    <attributes>

        <basic name="name">
            <column name="name" length="36" nullable="false" />
        </basic>

        <basic name="addressid">
            <column name="addressid" length="36"/>
        </basic>

        <one-to-one name="address" fetch="EAGER">
            <join-column name="addressid"
                referenced-column-name="id" insertable="false" updatable="false"
                nullable="false" />
        </one-to-one>

    </attributes>
</entity>
<entity name="address" class="com.csam.mtp.wallet.wallet.Address"
    access="FIELD">
    <table name="address" />
    <attributes>
        <basic name="address">
            <column name="address" length="36" />
        </basic>
    </attributes>
</entity>

DB Script

CREATE TABLE address (
id VARCHAR (50) not null,
address VARCHAR(50),
primary key(id)

);

CREATE TABLE person (
id VARCHAR (50) not null,
name VARCHAR(50),
addressid VARCHAR(50),
primary key(id),
foreign key (addressid) REFERENCES address(id),

);

Driver class

Address address = new Address();
    address.setAddress("test");
    address = addressRepository.save(address);

    Person person = new Person("Mike");

    //person.setAddressId(address.id());

    try {
        person = personRepository.save(person);
    } catch (Exception e) {
        e.printStackTrace();
    }

    System.out.println(personRepository.exists(person.getID()));
    Person savedPerson = personRepository.findOne(person.getID());
    // Asserts
    assertNotNull(savedPerson);
    assertNotNull(savedPerson.id());

While saving person If i don't set address id then it saves person successfully, exists returns true but find one api always returns null

while saving person if first I save address and set address id in person and save it then It saves person successfully, exists return true and find one api return Person object with address object (as it is eager)

So here below is my query,

Is it in case of one to one mapping with eager fetch on child, child must be saved and set in parent before the saving of parent?

I tried to find out related arcticle but not able to get one, Please assist.

Thanks in advance

Upvotes: 0

Views: 1169

Answers (2)

Vlad Mihalcea
Vlad Mihalcea

Reputation: 154090

In your case the Address is the parent and the Person is the Child. That's because the Child points to the Parent through the addressId FK.

Because you don't have a bi-directional association, you shouldn't have insertable="false" updatable="false"

With these settings, Hibernate won't be able to include the addressId in the INSERT or the UPDATE query.

  1. Remove insertable="false" updatable="false"
  2. Remove the addressId column too, since you can reference it through address.id
  3. Add cascade from Person to Address:

    <one-to-one name="address" fetch="EAGER">
        <join-column name="addressid"
            referenced-column-name="id" nullable="false" />
        <cascade>
            <cascade-persist/>
            <cascade-merge/>
        </cascade>
    </one-to-one>       
    

Probably it would be better to have a bi-directional association so that an Address has also a reference to a Person and in that case you should probably have a one-to-many association, since an Address may have multiple Persons.

Upvotes: 1

Sanjay Jain
Sanjay Jain

Reputation: 3587

Finally got the solution with nullable=true, as below:

<one-to-one name="address" fetch="EAGER">
        <join-column name="addressid"
            referenced-column-name="id" insertable="false" updatable="false"
            nullable="true" />
</one-to-one>

Upvotes: 0

Related Questions