I haven't included columns that are not relevant to this question. I'll briefly describe what I want to do, and then go forward to explain the problem. I am trying to model a graph in the database. Each vertex has multiple edges (Vertex->Edge: One-to-many) and each vertex physical Id is mapped to a unique vertexId (one-to-one). This mapping between virtual vertexIds and physicalResourceIds are for another purpose.
Inshort, my question is that I want to cascade deletes to edges when I delete vertex, but I don't want to cascade delete to vertex when I delete edges. I have a database that has three tables and their model classes are as shown below:
public class VertexModel implements java.io.Serializable{
/**
* @return the mapping
*/
@OneToOne(mappedBy = "vertex", fetch = FetchType.EAGER, cascade = {CascadeType.ALL} )
public PhysicalResourceToVertexMappingModel getMapping() {
return mapping;
}
/**
* @param mapping the mapping to set
*/
public void setMapping(PhysicalResourceToVertexMappingModel mapping) {
this.mapping = mapping;
}
/**
* @return the edgeSet
*/
@OneToMany(mappedBy = "sourceVertex", fetch = FetchType.EAGER, cascade = {CascadeType.ALL} )
public Set<EdgeModel> getSourceEdgeSet() {
return sourceEdgeSet;
}
/**
* @param edgeSet the edgeSet to set
*/
public void setSourceEdgeSet(Set<EdgeModel> sourceEdgeSet) {
this.sourceEdgeSet = sourceEdgeSet;
}
/**
* @return the destinationEdgeSet
*/
@OneToMany(mappedBy = "destinationVertex", fetch = FetchType.EAGER, cascade = {CascadeType.ALL} )
public Set<EdgeModel> getDestinationEdgeSet() {
return destinationEdgeSet;
}
/**
* @param destinationEdgeSet the destinationEdgeSet to set
*/
public void setDestinationEdgeSet(Set<EdgeModel> destinationEdgeSet) {
this.destinationEdgeSet = destinationEdgeSet;
}
public class EdgeModel implements java.io.Serializable {
/**
* Gets the source vertex's vertex
* @return the sourceVertex
*/
@ManyToOne(targetEntity = VertexModel.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "SOURCE_VERTEX_ID", nullable = false)
public VertexModel getSourceVertex() {
return this.sourceVertex;
}
/**
* Sets the source vertex
* @param sourceVertex the sourceVertex to set
*/
public void setSourceVertex(VertexModel sourceVertex) {
this.sourceVertex = sourceVertex;
}
/**
* Gets the destination vertex
* @return the destinationVertex
*/
@ManyToOne(targetEntity = VertexModel.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "DESTINATION_VERTEX_ID", nullable = false)
public VertexModel getDestinationVertex() {
return this.destinationVertex;
}
/**
* Sets the destination vertex
* @param destinationVertex
*/
public void setDestinationVertex(VertexModel destinationVertex) {
this.destinationVertex = destinationVertex;
}
public class PhysicalResourceToVertexMappingModel implements java.io.Serializable{
/**
* @return the vertex
*/
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name="VERTEX_ID")
public VertexModel getVertex() {
return vertex;
}
/**
* @param vertex the vertex to set
*/
public void setVertex(VertexModel vertex) {
this.vertex = vertex;
}
Now, my problem is that when I delete a vertex, all edges incident on this vertex get deleted too, which is what is desirable. But, what happens next is undesirable. When i delete an edge, all vertices that have that edge are deleted, and then these vertices delete the edge incident on them, which causes other vertices to get deleted and so on. Basically, the child-parent relationship isn't being mapped well enough.
In short, if this is the graph: V1 (E1) V2 (E2) V3 (E3) V4 where V are vertices and E are edges. Now, when I delete V1, E1 gets deleted which is expected. But then, V2 also gets deleted (because E1 got deleted) and then, V2 gets deleted and so on and the whole graph gets deleted.
What am I doing wrong here? Is my parent-child mapping (using @mappedBy) wrong? My deletion code is as follows:
Session session = this.getCurrentSession();
Criteria criteriaVertex = session.createCriteria(VertexModel.class);
Criteria criteriaMapper = session.createCriteria(PhysicalResourceToVertexMappingModel.class);
criteriaMapper.createAlias("vertex", "vertex")
.add(Restrictions.eq("vertex.clientId", clientId))
.add(Restrictions.eq("vertex.nodeId", nodeId ))
.add(Restrictions.eq(Constants.Columns.PHYSICAL_ID, physicalId));
PhysicalResourceToVertexMappingModel resultMapping = (PhysicalResourceToVertexMappingModel) criteriaMapper.uniqueResult();
String vertexId = resultMapping.getVertex().getVertexId();
criteriaVertex.add(Restrictions.eq(Constants.Columns.VERTEX_ID, vertexId));
VertexModel resultVertex = (VertexModel) criteriaVertex.uniqueResult();
//resultVertex.getSourceEdgeSet().clear();
//resultVertex.getDestinationEdgeSet().clear();
session.delete(resultMapping);
session.delete(resultVertex);
I tried to delete the entities as some StackOverflow users had mentioned on other questions, but that raises this exception: org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)
How do I go about deleting (either cascade or model parent-child relationship) so that when I delete a vertex, all edges incident get deleted, but when i delete an edge, no vertex is deleted?
EDIT: Since there were no replies, I just want to clarify that the problem is simple, I want to model a parent-child relationship such that deleting the child doesn't delete the parent. (If in addition to this I get the feature where adding a child will lead to saving in the parent, that would be even better). How do I do this? Are my annotations wrong? Thanks