2

I have a simple one-to-many relationship between Employee & Phone entities.

I have 2 issues here.

Scenario 1 :

@Entity
public class Employee {
    @Id
    @GeneratedValue
    private long id;

    private String firstName;
    private String lastName;
    private double salary;

    @OneToMany
    @JoinColumn(name = "parent_id", referencedColumnName = "id", insertable=false, updatable=false)
    private List<Phone> phones = new ArrayList<Phone>(0);

// Setters & Getter methods

}

Phone.java

@Entity
public class Phone {
    @Id
    private long id;
    private String type;
    private int areaCode;
    private String phoneNumber;

// Setter & Getters

}

Now I created employee instance and added 2 phones to it.

Employee e1 = new Employee(10,"Bob", "Way",50000);
Phone p1 = new Phone(1,"home",613,"792-0000");
Phone p2 = new Phone(2,"work",613,"896-1234");          
e1.addPhone(p1);
e1.addPhone(p2);

Then in hibernate, if I use below code:

session.save(e1);
session.save(p1);
session.save(p2);

or if I save phone then employee

session.save(p1);
session.save(p2);
session.save(e1);

In both cases, Hibernate just runs insert queries with out any update queries but the foreign key is set to NULL.

mysql> select * from Phone;
+----+----------+-------------+------+-----------+
| id | areaCode | phoneNumber | type | parent_id |
+----+----------+-------------+------+-----------+
|  1 |      613 | 792-0000    | home |      NULL |
|  2 |      613 | 896-1234    | work |      NULL |
|  3 |      416 | 123-4444    | work |      NULL |
+----+----------+-------------+------+-----------+

How can I fix this? Please let me know where I made mistake.

Scenario 2 :

Now if I made change to my @JoinColumn in Employee table like below:

@JoinColumn(name = "parent_id")

Then Hibernate is generating **insert** then update queries to map the foreign key properly.

Hibernate: insert into Employee (firstName, lastName, salary) values (?, ?, ?)
Hibernate: insert into Phone (areaCode, phoneNumber, type, id) values (?, ?, ?, ?)
Hibernate: insert into Phone (areaCode, phoneNumber, type, id) values (?, ?, ?, ?)
Hibernate: insert into Phone (areaCode, phoneNumber, type, id) values (?, ?, ?, ?)
Hibernate: update Phone set parent_id=? where id=?
Hibernate: update Phone set parent_id=? where id=?

When Hibernate runs the insert on Employee table then it gets the employee id there itself, then why does Hibernate runs additional update query when it can just run a single insert query on Phone table by including the foreign key value?

I understand that in update query it is adding the foreign key, but I would like to know why this is not managed in insert query itself on Phone table. Can you please explain this?

Scenario 3:

If I say like this:

@JoinColumn(name = "OWNER_ID", insertable=false, updatable=false, nullable=false)

Then I get below exception:

Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value : onetomany.Phone._phones_OWNER_IDBackref
learner
  • 6,062
  • 14
  • 79
  • 139
  • 1
    Please refer links http://stackoverflow.com/questions/35223952/how-to-avoid-hibernate-generating-two-queries-for-an-update-with-onetomany?lq=1 and http://stackoverflow.com/questions/22591684/hibernate-many-to-one-updating-foreign-key-to-null – Nitin Prabhu Feb 14 '16 at 09:18
  • For scenarios 1) and 3), you specified `insertable=false, updatable=false`, so it is obvious why the values are not saved. For scenario 2), as already pointed by @NitinPrabhu, duplicate of those questions. – Dragan Bozanovic Feb 14 '16 at 11:37
  • @DraganBozanovic, can you please tell when we need to use `insertable=false, updatable=false` ? – learner Feb 14 '16 at 15:08

1 Answers1

2

You have a Employee and an Phone.

You'd like to add insertable=false, updatable=false to the @OneToMany relationship with the Employee entity in the Phone entity, simply because it's not the responsibility of the Phone entity to create or update a Employee. It's the other way round.

@Entity
public class Employee {

    @Id
    @GeneratedValue
    private long id;

    private String firstName;
    private String lastName;
    private double salary;

    @OneToMany(mappedBy="person", cascade=CascadeType.ALL)
    private List<Phone> phones = new ArrayList<Phone>(0);

    // Setters & Getter methods

}

@Entity
public class Phone {

    @Id
    private long id;
    private String type;
    private int areaCode;
    private String phoneNumber;

    @ManyToOne
    @JoinColumn(name="PHONE_FK")
    @Column(insertable=false, updatable=false)
    private Employee employee;

}
gian1200
  • 3,670
  • 2
  • 30
  • 59
Nitin Prabhu
  • 624
  • 6
  • 10
  • `@JoinColumn` and `@Column` cannot be used together in JPA. You will get a Runtime exception. For more, refer: https://stackoverflow.com/questions/4121485/columns-not-allowed-on-a-manytoone-property – raksheetbhat Jul 06 '20 at 12:40