it-swarm.com.ru

Хранилище данных Spring не удаляет объект ManyToOne

В настоящее время я пытаюсь использовать репозиторий Spring Data для удаления некоторых из моих сущностей. Вызов удаления работает без каких-либо исключений/сообщений об ошибках, но впоследствии объект не удаляется.

Это мои сущности:

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, я вижу, что hibernate даже не пытается удалить. Единственное, что происходит, это два оператора 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

Оказывается, cascade = CascadeType.ALL на сообщениях, кажется, проблема. Без этого удаление работает нормально (но мне не хватает каскада изменений в сообщениях)

28
Nitek

Кажется, проблема в том, что вы используете cascade=CascadeType.ALL, который также включает CascadeType.PERSIST. CascadeType.PERSIST означает, что дочерняя сущность полностью управляется родителем, и вы не можете удалить ее напрямую. Для того, чтобы удалить, вам просто нужно удалить его от родителя.

Вы можете просто добавить другой CascadeTypes вместо всех. например, CascadeType.REMOVE, если единственное, что вам нужно, это удалить дочерний элемент, если родительский элемент удален.

62
user2936091

Основываясь на превосходном ответе пользователя 2936091 выше, я просто хотел упомянуть (связанный) обходной путь, на который я наткнулся сегодня: если родительская сущность не извлекается в контекст Hibernate, вы можете удалить ее напрямую.

В моем случае это было достигнуто путем установки fetch = FetchType.LAZY в отношении @ManyToOne. В любом случае, я хотел получить это изменение по соображениям производительности и заметил, что без нетерпеливо извлеченного родителя Hibernate может удалить его с помощью вызова метода репозитория.

3
chut

Это потому, что вы устанавливаете mappedBy = "board" в классе Post, тем самым вы говорите, что хозяином Post является Board.

0
Vyncent