Reputation: 649
o Some idiomatic clarifications for a better understanding: capa means layer and mapa means map
o A layer might be used in different maps and a map might contain many different layers
o When you delete a layer, associations with maps must disappear, but maps themselves continue existing.
o Conversely, when you delete a map, associations with layers must disappear, but layers themselves continue existing.
o The mapping code:
@Entity
@Table(name = "CAPA")
public class Capa implements Serializable {
@ManyToMany(fetch=FetchType.LAZY, mappedBy="capas")
private Set<Mapa> mapas;
}
And
@Entity
@Table(name = "MAPA")
public class Mapa implements Serializable {
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name="mapa_capa", joinColumns={@JoinColumn(name="idMapa")}, inverseJoinColumns={@JoinColumn(name="idCapa")})
private Set<Capa> capas;
}
o To remove the link between a layer(capa) and its maps (mapas), I've tried:
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);
}
And that does not work. Both sets (m.capas and c.mapas) remain untouched.
Thanks for helping.
Upvotes: 0
Views: 477
Reputation: 1595
Your Capa c
is one object. The persistence provider can only know the c
actually exists in the set of Mapa
, if you have implemented the hashCode
and equals
properly in your Capa
class. Else, there might be a case, when hibernate will never know that c
actually exists in m
and hence m.getCapas().remove(c)
will never actually remove c
from m
. You can check this by evaluating the returned value from the remove call. I am pretty sure it will be false
.
The better thing to do here is to check the primary key of objects and then remove the actual object
from the sets.
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);
}
This however has an extra for loop.
The best thing to do is to implement equals
and hashCode
methods in all your entities.
Upvotes: 1
Reputation: 3927
You need to call to flush in order that the change will take affect in the database. you didnt call to flush and you call to refresh so the db copy override your change
Upvotes: 0