Spring Хранилище данных не удаляет объект ManyToOne
В настоящее время я пытаюсь использовать репозиторий данных Spring для удаления некоторых моих объектов. Вызов удаления работает без сообщений об исключениях/ошибках, но после этого объект не удаляется.
Это мои сущности:
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>();
}
и
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;
}
Репозиторий настолько прост, насколько это возможно:
@Repository
public interface PostRepository extends CrudRepository<Post, Long> {
}
Вызов удаления - это что-то вроде
postRepository.delete(50);
Любые идеи, почему это изменение не отражено в базе данных?
Изменить 1:
Я нашел обходное решение, но я до сих пор не понимаю, что такое настоящая проблема.
Он "работает", если я удаляю сообщение вроде этого (есть несколько исключений из-за ограничений ограничений, но все равно сообщение удаляется):
post.setBoard(null);
postRepo.delete(post);
Изменить 2:
Когда я смотрю на выполняемые SQL-запросы, я вижу, что спящий режим даже не пытается удалить. Единственное, что происходит, это те два оператора 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=?
Изменить 3
Выключает каскад = CascadeType.ALL на сообщениях, кажется, проблема. Без него удаление отлично работает (но сейчас я пропускаю каскад изменений в сообщениях)
Ответы
Ответ 1
Проблема заключается в том, что вы используете cascade=CascadeType.ALL
, который также включает CascadeType.PERSIST
. CascadeType.PERSIST
означает, что дочерний объект полностью управляется родителем, и вы не можете удалить его напрямую. Для удаления вам просто нужно удалить его из родителя.
Вы можете просто добавить другой CascadeTypes
вместо всех. например CascadeType.REMOVE
, если единственное, что вы захотите, это удалить дочерний элемент, если родитель удален.
Ответ 2
Основываясь на отличном ответе от user2936091 выше, я просто хотел упомянуть (связанное) обходное решение, которое я наткнулся на сегодняшний день: если родительский объект не загружается в контекст Hibernate, вы можете удалить его напрямую.
В моем случае это было достигнуто установкой fetch = FetchType.LAZY
в отношении @ManyToOne
. В любом случае, я хотел это изменение по причинам производительности, и заметил, что без родительского желаемого Hibernate было бы свободно удалять его с помощью вызова метода репозитория.
Ответ 3
Это связано с тем, что вы устанавливаете mappedBy = "board" в классе Post, делая это, чтобы сообщить, что хозяин Post - это Board.
Ответ 4
Простая альтернатива:
@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);
}
Ответ 5
cascade = CascadeType.PERSIST используется для обновления вставки в обе стороны, но для удаления это ограничит.
@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;