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)
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.
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.
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;
Dies liegt daran, dass Sie mappedBy = "board" on Post-Klasse setzen. Dadurch sagen Sie, dass der Master von Post Board ist.
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);
}