web-dev-qa-db-de.com

Spring Data Repository löscht ManyToOne Entity nicht

Ich versuche gerade, ein Spring Data-Repository zu verwenden, um einige meiner Entitäten zu löschen. Der Löschaufruf funktioniert ohne Ausnahmen/Fehlermeldungen, die Entität wird danach jedoch nicht gelöscht.

Das sind meine Wesenheiten:

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>();
}

und

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;
}

Das Repository ist so einfach wie möglich:

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

Der Löschanruf ist so ähnlich

postRepository.delete(50);

Irgendwelche Ideen, warum diese Änderung nicht in der Datenbank angezeigt wird?

Edit 1:

Ich habe eine Problemumgehung gefunden, aber ich verstehe immer noch nicht, was das eigentliche Problem ist ... Es funktioniert, wenn ich die Post so lösche (es gibt ein paar Ausnahmen aufgrund von Zwangsverletzungen, aber die Post wird trotzdem gelöscht ):

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

Edit 2:

Wenn ich mir die ausgeführten SQL-Anweisungen anschaue, kann ich feststellen, dass der Ruhezustand nicht einmal versucht zu löschen. Das einzige, was passiert, sind diese beiden select-Anweisungen:

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=?

Bearbeiten 3

Stellt sich heraus, dass die Kaskade = CascadeType.ALL für Posts das Problem zu sein scheint. Ohne es funktioniert das Löschen gut (aber ich vermisse jetzt die Kaskade der Änderungen an Beiträgen)

28
Nitek

Das Problem scheint zu sein, dass Sie cascade=CascadeType.ALL verwenden, zu dem auch CascadeType.PERSIST gehört. CascadeType.PERSIST bedeutet, dass die untergeordnete Entität vollständig vom übergeordneten Element verwaltet wird und nicht direkt gelöscht werden kann. Um zu löschen, müssen Sie es nur aus dem übergeordneten Element entfernen.

Sie können einfach die andere CascadeTypes anstelle von allen hinzufügen. B. CascadeType.REMOVE, wenn Sie nur das untergeordnete Element entfernen möchten, wenn das übergeordnete Element entfernt wird.

62
user2936091

Aufbauend auf der hervorragenden Antwort von user2936091 oben wollte ich nur eine (verwandte) Problemumgehung nennen, auf die ich heute gestoßen bin: Wenn die übergeordnete Entität nicht in den Hibernate-Kontext abgerufen wird, können Sie sie direkt löschen.

In meinem Fall wurde dies durch Einstellen von fetch = FetchType.LAZY in der @ManyToOne-Beziehung erreicht. Ich wollte diese Änderung aus Leistungsgründen trotzdem und bemerkte, dass Hibernate ohne das überholte Elternteil frei über den Repository-Methodenaufruf gelöscht werden konnte.

3
chut

cascade = CascadeType.PERSIST wird zum Aktualisieren der Einfügung auf beiden Seiten verwendet, zum Löschen jedoch eingeschränkt.

@ManyToOne(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY)
//  @JoinColumn(name = "qid")
    @JoinColumn(name = "qid", referencedColumnName = "qid", foreignKey = @ForeignKey(name = "qid"), nullable = false)
    // @JsonIgnore
    @JsonBackReference
    private QueueGroup queueGroup;
0
Shubham

Dies liegt daran, dass Sie mappedBy = "board" on Post-Klasse setzen. Dadurch sagen Sie, dass der Master von Post Board ist.

0
Vyncent

Eine einfache Alternative:

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

@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query(value = "DELETE FROM post WHERE id = ?1", nativeQuery = true)
void deleteById(long postId);

}
0
Michel Fortes