Hibernate EntityManager:如何删除关联
o为了更好地理解,需要进行一些惯用的澄清:capa表示层,mapa表示映射 o一个图层可能用于不同的地图,并且一个地图可能包含许多不同的图层 o删除图层时,与贴图的关联必须消失,但贴图本身仍然存在 o相反,删除地图时,与图层的关联必须消失,但图层本身仍然存在 o映射代码:Hibernate EntityManager:如何删除关联,hibernate,many-to-many,associations,entitymanager,Hibernate,Many To Many,Associations,Entitymanager,o为了更好地理解,需要进行一些惯用的澄清:capa表示层,mapa表示映射 o一个图层可能用于不同的地图,并且一个地图可能包含许多不同的图层 o删除图层时,与贴图的关联必须消失,但贴图本身仍然存在 o相反,删除地图时,与图层的关联必须消失,但图层本身仍然存在 o映射代码: @Entity @Table(name = "CAPA") public class Capa implements Serializable { @ManyToMany(fetch=FetchType.LAZ
@Entity
@Table(name = "CAPA")
public class Capa implements Serializable {
@ManyToMany(fetch=FetchType.LAZY, mappedBy="capas")
private Set<Mapa> mapas;
}
@实体
@表(name=“CAPA”)
公共类Capa实现可序列化{
@ManyToMany(fetch=FetchType.LAZY,mappedBy=“capas”)
私有集映射;
}
及
@实体
@表(name=“MAPA”)
公共类Mapa实现了可序列化{
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name=“mapa_capa”,joinColumns={@JoinColumn(name=“idMapa”)},inverseJoinColumns={@JoinColumn(name=“idCapa”)})
私有集capas;
}
o要删除图层(capa)及其贴图(mapas)之间的链接,我尝试了以下操作:
Capa c = findCapa();
Iterator<Mapa> itms = c.getMapas().iterator();
while (itms.hasNext()) {
Mapa m = itms.next();
m.getCapas().remove(c);
c.getMapas().remove(m);
getEntityManager().refresh(m);
getEntityManager().refresh(c);
}
Capa c=findCapa();
迭代器itms=c.getMapas().Iterator();
while(itms.hasNext()){
Mapa m=itms.next();
m、 getCapas()。删除(c);
c、 getMapas().remove(m);
getEntityManager().refresh(m);
getEntityManager()。刷新(c);
}
这是行不通的。两组(m.capas和c.mapas)保持不变
感谢您的帮助。您需要调用flush以使更改在数据库中生效。您没有调用flush,而是调用refresh,因此数据库副本将覆盖您的更改。您的Capa
c
是一个对象。如果您在Capa
类中正确地实现了hashCode
和equals
,则持久性提供程序只能知道c
实际上存在于Mapa
集中。否则,可能会有这样一种情况,hibernate永远不会知道c
实际上存在于m
中,因此m.getCapas().remove(c)
永远不会从m
中实际删除c
。您可以通过计算remove调用返回的值来检查这一点。我很确定它将是假的
这里要做的更好的事情是检查对象的主键,然后从集合中删除实际对象
Capa c = findCapa();
Iterator<Mapa> itms = c.getMapas().iterator();
while (itms.hasNext()) {
Mapa m = itms.next();
foreach(Capa c1 : m.getCapas()) {
if(c1.getId().equals(c.getId())) {
m.getCapas().remove(c1);
}
}
//No need to remove m from c as Mapa is the owning side
getEntityManager().refresh(m);
getEntityManager().refresh(c);
}
Capa c=findCapa();
迭代器itms=c.getMapas().Iterator();
while(itms.hasNext()){
Mapa m=itms.next();
foreach(capac1:m.getCapas()){
如果(c1.getId().equals(c.getId())){
m、 getCapas()。移除(c1);
}
}
//不需要从c中删除m,因为Mapa是拥有方
getEntityManager().refresh(m);
getEntityManager()。刷新(c);
}
然而,这有一个额外的for循环
最好的做法是在所有实体中实现
equals
和hashCode
方法。感谢您的回答,它不起作用。实际上,在我发布代码之前,我已经用flush处理过了。你有没有查看日志来检查sql是否触发到数据库中?您可以使用HiberNet日志或hibernate show_sql或sql profiler进行此操作。
Capa c = findCapa();
Iterator<Mapa> itms = c.getMapas().iterator();
while (itms.hasNext()) {
Mapa m = itms.next();
foreach(Capa c1 : m.getCapas()) {
if(c1.getId().equals(c.getId())) {
m.getCapas().remove(c1);
}
}
//No need to remove m from c as Mapa is the owning side
getEntityManager().refresh(m);
getEntityManager().refresh(c);
}