Spring Data Repository不会删除ManyToOne Entity

Nit*_*tek 32 java spring hibernate spring-data-jpa

我目前正在尝试使用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>();
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

存储库尽可能简单:

@Repository
public interface PostRepository extends CrudRepository<Post, Long> {
}
Run Code Online (Sandbox Code Playgroud)

删除调用类似于

postRepository.delete(50);
Run Code Online (Sandbox Code Playgroud)

有什么想法为什么这种变化没有反映在数据库中?

编辑1:

我找到了一个解决方法,但我仍然不明白真正的问题是什么.如果我像这样删除帖子它会"有效"(由于约束违规而有一些例外,但邮件仍被删除):

post.setBoard(null);
postRepo.delete(post);
Run Code Online (Sandbox Code Playgroud)

编辑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=?
Run Code Online (Sandbox Code Playgroud)

编辑3

结果cascade = CascadeType.ALL上的帖子似乎是个问题.没有它,删除工作正常(但我现在错过了对帖子的级联更改)

小智 68

问题似乎是你正在使用cascade=CascadeType.ALL,其中也包括CascadeType.PERSIST.CascadeType.PERSIST表示子实体完全由父实体管理,您无法直接删除它.要删除,只需将其从父项中删除即可.

你可以添加另一个CascadeTypes而不是全部.例如CascadeType.REMOVE,如果父母被移除,你唯一想要的就是移除孩子.

  • 你知道如果有理由不抛出异常,我的意思是我试图删除并且不可能有一些约束,如果通知会不会好的? (9认同)

chu*_*hut 8

基于上面来自 user2936091 的出色回答,我只想提一下我今天偶然发现的一个(相关)解决方法:如果父实体没有被提取到 Hibernate 上下文中,你可以直接删除它。

在我的情况下,这是通过设置实现fetch = FetchType.LAZY@ManyToOne关系。无论如何,出于性能原因,我希望进行此更改,并注意到没有父级急切获取的 Hibernate 可以通过存储库方法调用自由删除它。