web-dev-qa-db-fra.com

Spring Data Repository ne supprime pas l'entité ManyToOne

J'essaie actuellement d'utiliser un référentiel Spring Data pour supprimer certaines de mes entités. L'appel de suppression fonctionne sans exception ni message d'erreur, mais l'entité n'est pas supprimée par la suite.

Ce sont mes entités:

public class Board implements Serializable {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "uuid2")
    @Column(columnDefinition = "BINARY(16)")
    private UUID uuid;

    @OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval = true, mappedBy = "board")
    private List<Post> posts = new ArrayList<Post>();
}

et

public class Post implements Serializable {

    @Id
    @GeneratedValue
    private long id;

    @ManyToOne(optional = false)
    @JoinColumn(name="board_uuid", updatable = false, nullable = false)
    @JsonBackReference
    private Board board;
}

Le référentiel est aussi simple que possible:

@Repository
public interface PostRepository extends CrudRepository<Post, Long> {
}

L'appel de suppression est quelque chose comme

postRepository.delete(50);

Des idées pour lesquelles ce changement ne se reflète pas dans la base de données?

Modifier 1:

J'ai trouvé une solution de contournement, mais je ne comprends toujours pas quel est le véritable problème . Cela "fonctionne" si je supprime la publication de cette manière (il existe quelques exceptions en raison de violations de contrainte, mais la publication est toujours supprimée. ):

post.setBoard(null);
postRepo.delete(post);

Edit 2:

Lorsque je regarde les instructions SQL exécutées, je constate que hibernate n’essaye même pas de le supprimer. La seule chose qui se passe sont ces deux déclarations select:

Hibernate: select post0_.id as id1_1_0_, post0_.board_uuid as board_uu6_1_0_, post0_.content as content2_1_0_, post0_.x as x3_1_0_, post0_.y as y4_1_0_, post0_.z as z5_1_0_, board1_.uuid as uuid1_0_1_ from Post post0_ left outer join Board board1_ on post0_.board_uuid=board1_.uuid where post0_.id=?
Hibernate: select posts0_.board_uuid as board_uu6_0_0_, posts0_.id as id1_1_0_, posts0_.id as id1_1_1_, posts0_.board_uuid as board_uu6_1_1_, posts0_.content as content2_1_1_, posts0_.x as x3_1_1_, posts0_.y as y4_1_1_, posts0_.z as z5_1_1_ from Post posts0_ where posts0_.board_uuid=?

Modifier 3

Il s'avère que le cascade = CascadeType.ALL sur les publications semble être le problème. Sans cela, la suppression fonctionne bien (mais la cascade de modifications apportées aux publications me manque maintenant)

28
Nitek

Le problème semble être que vous utilisez cascade=CascadeType.ALL, qui inclut également CascadeType.PERSIST. CascadeType.PERSIST signifie que l'entité enfant est entièrement gérée par le parent et que vous ne pouvez pas la supprimer directement. Pour le supprimer, il vous suffit de le supprimer du parent.

Vous pouvez simplement ajouter l'autre CascadeTypes au lieu de tout. Par exemple, CascadeType.REMOVE, si la seule chose que vous souhaitez est de supprimer l'enfant si le parent est supprimé.

62
user2936091

En me basant sur l'excellente réponse de l'utilisateur 2936091 ci-dessus, je voulais juste mentionner une solution de contournement (liée) que je suis tombée sur aujourd'hui: si l'entité mère n'est pas récupérée dans le contexte d'Hibernate, vous pouvez la supprimer directement.

Dans mon cas, cela a été réalisé en définissant fetch = FetchType.LAZY sur la relation @ManyToOne. De toute façon, je voulais ce changement pour des raisons de performances et j'ai remarqué que, sans le parent recherché, Hibernate était libre de le supprimer via l'appel de la méthode de référentiel.

3
chut

C'est parce que vous définissez mappedBy = "board" sur la classe Post, vous indiquez que le maître de Post est Board.

0
Vyncent