Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

@ManyToMany with cascade = CascadeType.REMOVE removes associations AND entities

I have 2 entities: Group and Grouped, with 1 ManyToMany association.

In database, the Association table has a NOT NULL FK on both Group and Grouped.

I want Hibernate to delete the association but not the group when all grouped are deleted.

Code to delete a Grouped entity:

@Autowired
private final GroupedRepository groupedRepository;

public void delete(Grouped groupedToRemove) {
    groupedRepository.delete(groupedToRemove);
}

If I set cascade = CascadeType.ALL or cascade = CascadeType.REMOVE, my Group entities are deleted when I delete a Grouped entity, not only the associations:

@ManyToMany(cascade = CascadeType.ALL, // same behavior with CascadeType.REMOVE
        mappedBy = "grouped", 
        targetEntity = Group.class)
private Set<Group> groups = new HashSet<>();

If I remove the cascade, hibernate tries to set group_id=null and it throws a ModelConstraintException. I don't want to set the FK as nullable.

Group entity:

@Entity
@Table(name = "groups")
@Getter
@Setter
public class Group {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToMany(targetEntity = Grouped.class)
    @JoinTable(
            name = "association",
            joinColumns = @JoinColumn(name = "group_id", nullable = false, updatable = false),
            inverseJoinColumns = @JoinColumn(name = "grouped_id", nullable = false, updatable = false)
    )
    private Set<Grouped> grouped= new HashSet<>();
}

Grouped entity:

@Entity
@Table(name = "grouped")
@Getter
@Setter
public class Grouped {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToMany(mappedBy = "grouped", targetEntity = Group.class)
    private Set<Group> groups= new HashSet<>();
}
like image 961
Pleymor Avatar asked Sep 02 '15 13:09

Pleymor


1 Answers

That's the expected behavior. REMOVE cascading means: when removing this entity, also remove the associated entities. It makes no sense on a ManyToXxx, since obviously, other entities are still referencing the associated entity.

If you want to delete a Grouped, but leave the associated Groups there, you need to remove the association between the two entities first:

for (Group group : grouped.getGroups()) {
    group.getGrouped().remove(grouped);
}
grouped.getGroups().clear();

and then remove the Grouped entity, which is not associated to any Group anymore.

like image 105
JB Nizet Avatar answered Sep 23 '22 17:09

JB Nizet