Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

jpa - Hibernate One To One Mapping , how not to insert child but bind to it

Does someone knows a method to use a One To One Mapping where you save the parent but not inserting any children. Maybe the children already exist so I need to create a NEW Parent and just update an existing CHILD table row (with the new PARENT ID as FK).

Thanks !


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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..

:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...