简体   繁体   中英

Hibernate throws Exception while trying to delete Entity that in ManyToMany relationship

Team and TeamMember are in ManyToMany relationship. When I tried to delete team like this:

public void deleteTeam(int id) {
        Team team = (Team) getCurrentSession().get(Team.class, id);
        getCurrentSession().delete(team);
}

It gave:

org.springframework.dao.InvalidDataAccessApiUsageException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.sprhib.model.Team#1]; 
    nested exception is org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.sprhib.model.Team#1]

ThenI tried to delete all teams from team member entities that are holding THE TEAM I need to delete:

public void deleteTeam(int id) {
        Team team = getTeam(id);
        if(team != null){
            for(TeamMember tm: team.getTeamMembers()){
                for(Team t: tm.getTeams()){
                    if(t.getId() == team.getId()){
                        tm.getTeams().remove(t);
                    }
                }
            }
            getCurrentSession().delete(team);
        }
    }

But the same error stays. First of all I expected Hibernate to manage all related entities in ManyToMany relation accordingly since they have annotations. But it refuses to work. WTF?

Team

@Entity
@Table(name="teams")
public class Team {


    private int id;

    private String name;

    private int rating;

    private Set<TeamMember> teamMembers;

    private Organization organization;

    @Id
    @NotNull
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Length(max = 45)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @NotNull
    @Range(min = 0,max = 10)
    public int getRating() {
        return rating;
    }
    public void setRating(int rating) {
        this.rating = rating;
    }

    @NotNull
    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE})
    @JoinColumn(name = "FK_Organization_id", nullable = false)
    public Organization getOrganization() {
        return organization;
    }

    public void setOrganization(Organization organization) {
        this.organization = organization;
    }

    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    @JoinTable(name = "team_member", joinColumns =
        @JoinColumn(name = "FK_Team_id", referencedColumnName= "id"),
            inverseJoinColumns = @JoinColumn(name = "FK_Member_id", referencedColumnName = "id")
    )
    public Set<TeamMember> getTeamMembers() {
        return teamMembers;
    }

    public void setTeamMembers(Set<TeamMember> teamMembers) {
        this.teamMembers = teamMembers;
    }
}

TeamMember

@Entity
@Table(name="member")
public class TeamMember {

    private int id;

    private String name;

    private Set<Team> teams;

    @Id
    @NotNull
    @GeneratedValue(strategy = GenerationType.AUTO)
    public int getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
    @NotEmpty
    @Length(max=100)
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @NotNull
    @ManyToMany(fetch = FetchType.EAGER, mappedBy = "teamMembers", cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.REMOVE}) // cascade!!!
    public Set<Team> getTeams(){
        return teams;
    }

    public void setTeams(Set<Team> teams) {
        this.teams = teams;
    }


}

REMOVE should not be used with @ManyToMany from JPA 2.0 spec.

The relationship modeling annotation constrains the use of the cascade=REMOVE specification. The cascade=REMOVE specification should only be applied to associations that are specified as OneToOne or OneToMany. Applications that apply cascade=REMOVE to other associations are not portable.

There is vendor extension @OnDelete in Hibernate:

@OnDelete(action=OnDeleteAction.CASCADE)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM