问题
I am deleting entities
and hence rows from my database.
I do want to delete a certain entity and all of its child
rows. However, I do not want to delete any rows from its Parent
.
How can I accomplish this?
Kennel
is the Parent Entity
and Dog
is the entity I am deleting.
Please see code below to how I have linked the 2 in the Kennel Entity:
@OneToMany(cascade = CascadeType.MERGE, orphanRemoval = false)
@JoinColumn(name = "KENNEL_ID", referencedColumnName = "ID", updatable = true, insertable = true)
private Set<Dog> dogs;
Currently, when I delete dog entitie(s), its related Kennel entity is also being deleted.
EDIT: Mapping of Dog to Kennel:
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "KENNEL_ID")
private kennel kennel;
回答1:
Currently, when I delete dog entitie(s), its related Kennel entity is also being deleted.
The reason being you have cascade=CascadeType.ALL
set on ManyToOne
annotation. With this we are telling the ORM that when we delete (or any other operation) Dog
it should propagate the same operation to the Kennel
entity as well.
Remove cascade attribute in ManyToOne(cascade = CascadeType.ALL ).
Can I keep the @oneToMany relationship shown in kennel the same?
Few changes you might want to consider.
- No need of having
JoinColumn
annotation at bothoneToMany
andManyTone
side. - Consider using
mappedBy="kennel"
attribute inOneToMany
annotation and removeJoinColum
annotation onOneToMany
side. This makesManyToOne
the owning side and is also more efficient from SQLs that gets generated when you persistkennel
entity. You can check it yourself by enablingshow_sql
. - Regarding
cascade
attribute onOneToMany
whether to set it toALL
orMERGE
orPERSIST, MERGE
depends on which operations on parent entity you want to propagate to child entity. - Not sure if you have already implemented scaffolding code/methods to add/update the
oneToMany
relationship. If not, it is a good idea to implement them because that ensures the association is updated on both the ends. Refer to scaffolding code if needed.
回答2:
Switched your CascadeType.ALL operation from child table to parent table according to your need.
Here is the simple solution which is almost similar yours, and customize it based on your need.
@Entity(name = "Kennel")
@Table(name = "Kennel")
public class Kennel {
@Id
@Column(name = "Kennel_Id")
private long kennelId;
@Column(name = "Kennel_name")
private String KennelName;
//cascade = {CascadeType.REMOVE} OR orphanRemoval = true
@OneToMany(cascade = {CascadeType.ALL},orphanRemoval = true,fetch = fetchType.LAZY,mappedBy="dogKennel")
private Set<Dog> dogSet;
public long getKennelId() {
return kennelId;
}
public void setKennelId(long kennelId) {
this.kennelId = kennelId;
}
public String getKennelName() {
return KennelName;
}
public void setKennelName(String kennelName) {
KennelName = kennelName;
}
public Set<Dog> getDogSet() {
return dogSet;
}
public void setDogSet(Set<Dog> dogSet) {
this.dogSet = dogSet;
}
}
@Entity(name = "Dog")
@Table(name = "Dog")
public class Dog {
@Id
@Column(name = "Dog_Id")
private int dogId;
@ManyToOne
@JoinColumn(name = "Dog_Kennel_Id",referencedColumnName = "Kennel_Id")
private Kennel dogKennel;
@Column(name = "Dog_Name")
private String dogName;
public int getDogId() {
return dogId;
}
public void setDogId(int dogId) {
this.dogId = dogId;
}
public Kennel getDogKennel() {
return dogKennel;
}
public void setDogKennel(Kennel dogKennel) {
this.dogKennel = dogKennel;
}
public String getDogName() {
return dogName;
}
public void setDogName(String dogName) {
this.dogName = dogName;
}
}
//adding kennel=1 and dog=1
Kennel ken=new Kennel();
ken.setKennelId(1);
ken.setKennelName("KennelExample1");
HashSet<Dog> myDogSet=new HashSet<Dog>();
Dog dog=new Dog();
dog.setDogId(1);
dog.setDogName("ExampleDog1");
dog.setDogKennel(ken);
myDogSet.add(dog);
ken.setDogSet(myDogSet);
kennelRepo.save(ken);
//adding dog=2 under kennel=1
Dog dog2=new Dog();
dog2.setDogId(2);
dog2.setDogName("ExampleDog2");
Kennel dog2ken=new Kennel();
dog2ken.setKennelId(1);
dog2.setDogKennel(dog2ken);
dogRepo.save(dog2);
//adding dog=3 under kennel=1
Dog dog3=new Dog();
dog3.setDogId(3);
dog3.setDogName("ExampleDog3");
Kennel dog3ken=new Kennel();
dog3ken.setKennelId(1);
dog3.setDogKennel(dog3ken);
dogRepo.save(dog3);
//deleting dog=3
dog3=new Dog();
dog3.setDogId(3);
dogRepo.delete(dog3);
//deleting kennel=1 which in turn delete all dogs under
Kennel k=kennelRepo.findByKennelId(1);
kennelRepo.delete(k);
来源:https://stackoverflow.com/questions/36153570/hibernate-how-to-ensure-that-a-parent-is-not-deleted-when-all-its-child-entitie