By definition a One To One means that there exists a one to one relationship between the two entities and therefore its not recommended to have one of the pair of objects lying around as an orphan
when the other is deleted. Here is the official link for the same.
Having said that, one of the quirks with JPA/hibernate is that by default JPA OneToOne (or even OneToMany for that matter) have its orphanRemoval
field default to false
. This means that if one were to use the annotations without specifying this and use the defaults then that will result in orphaned entities.
I am not sure if the above quirk is what is causing your need to update existing 'CHILD' that is associated with a different 'PARENT' in a One To One relationship. If so, please go ahead & specify it, @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
and that will solve your problem.
If that is not the case and you would specifically like to NOT delete the 'CHILD' when you delete the 'PARENT' then i am not sure if One To One is the relationship mapping that should be used here. You can simply use a @ManyToOne
with defaults and it will work.
OK, based on your additional clarifying comment for my query i see that there is no parent-child relationship between the entities involved. Rather, the requirement here seems to be that of a One-to-one with Optional relationship between the entities.
This can then be modeled in two ways,
- One is to specify the optional nature of the relationship (nullable foreign key) along with the appropriate cascading in the
OneToOne
declaration like this, @OneToOne(optional = true, fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.REFRESH})
.
- Two is to avoid putting null values in the fk column to handle optional relationship by modeling the relationship with a join table (just like how we would do for a many-to-many relationship),
Like below snippet,
@Entity
@Table(name = "car")
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
@OneToOne(cascade = CascadeType.ALL)
@JoinTable(name = "car_parking",
joinColumns =
{ @JoinColumn(name = "car_id", referencedColumnName = "id") },
inverseJoinColumns =
{ @JoinColumn(name = "parkinglot_id", referencedColumnName = "id") })
private ParkingLot parkingLot;
//... getters and setters
}
@Entity
@Table(name = "parkinglot")
public class ParkingLot {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
//... getters and setters
}
The preference of one over the other might depend on how frequently we would we have nulls..
Hope that answers..
:
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…