Jack Jack - 1 year ago 59
Java Question

JPA @OneToMany + @JoinColumn remove issues an update on referencer table

With the following entities:

class Car {
@OneToMany(fetch = FetchType.LAZY, cascade = {})
//@JoinColumn(name = "id_car")
private Collection<Wheel> wheels;

class Wheel {
@JoinColumn(name = "id_car", referencedColumnName = "id")
@ManyToOne(fetch = FetchType.LAZY, cascade = {}, optional = false)
private Car idCar;

If I keep line 4 commented as shown above, system automatically creates a join-table for me. But this is not want I want, since Wheel has its own field for this link. That's why I've uncommented line 4 and join-table is not created anymore, which is fine. But now if I do

entityManager.remove(myCar); // remove car with id=1

I see underlying system call, before the actual delete, the following update sql statement:

Fine: UPDATE wheel SET id_car = ? WHERE (id_car = ?)
bind => [null, 1]

Which of course cause me the following:

ERROR: null value in column "id_car" violates not-null constraint

If I keep the above comment instead, I see underlying system perform two deletes:

Fine: DELETE wheel WHERE id_car = ?
bind => [1]

Fine: DELETE car WHERE id = ?
bind => [1]

Which could be fine, and of course it's working.. even if I'd prefer the underlying RDBMS doing its job as id_car is defined with "on delete cascade" rule. Problem remains as a useless additional join-table is created.

Question is: what annotation I must use to obtain the following:

  • no additional join-table created

  • on
    subsystem issues one delete and lets the rdbms do the dirty cascade job (If this is not possible, is fine to have multiple deletes issued by the application)

Answer Source

You should use the mappedBy Attribute in your OneToMany annotation to declare that the relationship is mapped by the idCar field of your Wheel class:

@OneToMany(fetch = FetchType.LAZY, mappedBy="idCar", cascade = {})
private Collection<Wheel> wheels;