achanCSI
achanCSI

Reputation: 53

Hibernate Cascade delete for one-to-many call SQL "update" instead of "delete"

I have a simple parent / children obj bi-directional relationship defined. I want to perform cascade delete so that when parent is removed, all the children would be removed as well with one 1 delete call from parent. Here are my pojo class declaration:

@Entity
@Table(name = "Agent_Assignment", schema = "xxx", catalog = "AAA")
public class AgentAssignment {
    private Set<AgentAssignmentAttr> attributes = new HashSet<AgentAssignmentAttr>();

    @OneToMany( fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true )
    @JoinColumn(name="Agent_Assignment_GUID")
    public Set<AgentAssignmentAttr> getAttributes() {
        return attributes;
    }

    public void setAttributes(Set<AgentAssignmentAttr> attributes) {
        this.attributes = attributes;
    }

}

@Entity
@Table(name = "Agent_Assignment_Attr", schema = "xxx", catalog = "AAA")
public class AgentAssignmentAttr {
    private AgentAssignment asgnmnt = null;

    @ManyToOne( fetch=FetchType.EAGER )
    @JoinColumn(name="Agent_Assignment_GUID", insertable=false, updatable=false)
    public AgentAssignment getAssignment() {
        return asgnmnt;
    }

    public void setAssignment(AgentAssignment assignment) {
        this.asgnmnt = assignment;
    }
}

And the code to delete is:

AgentAssignment assgnmnt = (...some HQL query to returns the AgentAssignment obj)
getSession().delete(assgnmnt);

When execute the above delete call, it throws exception:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

Basically, when log at the Hibernate log's SQL being executed, it doesn't call "update" on Agent_Assignment_Attr table's row it supposed to delete, but instead call "update" on the row to set the foreign key column "Agent_Assignement_GUID" to null, as shown below:

/* delete one-to-many com.cs.mytime.acr.model.AgentAssignment.attributes */ update
        MyTime.dbo.Agent_Assignment_Attr 
    set
        Agent_Assignment_GUID=null 
    where
        Agent_Assignment_GUID=?
2014/08/22 16:31:10.430 [TRACE] <http-bio-8080-exec-5> (BasicBinder.bind:81) - binding parameter [1] as [VARCHAR] - [CA91A4F3-6F7E-4188-B299-8E9DF17F0385]

Appreciate anybody to help to see if there's something I have missed and the right solution. Thanks.

Upvotes: 4

Views: 3958

Answers (2)

Antonio Petricca
Antonio Petricca

Reputation: 11070

In order to get a delete instead of an update I had to use this approach:

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
@JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID", updatable = false)
private List<ChildEntity> children;

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 692281

Your mapping is wrong. A bidirectional assocition must only define how the association is mapped once. What you have there is two distinct, unrelated associations that happen to use the same column. The mapping should be

@OneToMany(mappedBy="assignment", fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval=true )
public Set<AgentAssignmentAttr> getAttributes() {
    return attributes;
}

where mappedBy says: "I'm the inverse side of the bidirectional association defined and mapped on AgentAssignmentAttr.assignment, and

@ManyToOne( fetch=FetchType.EAGER )
@JoinColumn(name="Agent_Assignment_GUID")
public AgentAssignment getAssignment() {
    return asgnmnt;
}

Upvotes: 1

Related Questions