JPA + Hiberante如何删除多个依赖项上的实体

时间:2018-09-09 08:38:49

标签: hibernate jpa spring-data-jpa

我有一个User类,一个Conversation类和一个Message类。用户可以是发送者和接收者。 如果我的目标是,我不知道如何设置级联类型:

  • 如果删除了用户,请保留他/她的消息和对话
  • 如果两个用户都被删除,则删除对话和消息
  • 如果用户从对话中删除他/她的最后一条消息,请与其他用户保持对话
  • 如果用户删除一个对话,则仅从该对话中删除该用户,但保留对话本身和其他用户的所有消息
  • 删除两个用户之后,立即删除没有用户的对话以及这些对话的消息

在我看来,我可以在所有地方设置除CascadeType.Delete之外的所有CascadeType。 我必须手动检查每个删除。我想我无法在用户的消息上设置CascadeType.Delete例如,因为即使删除用户我也想保留它们,并且即使删除会话的所有参与者也要删除它们。 我不确定,但是我认为我无法对用户的邮件设置“孤立删除”,因为如果我删除用户,它将清除邮件列表并删除邮件。

@Entity
class User {

    @Id
    @GeneratedValue
    val id: Long = 0

    @OneToMany(mappedBy = "reviewer")
    lateinit var conversations: List<Conversation>

    @OneToMany(mappedBy = "sender")
    lateinit var sentMessages: List<Message>

    @OneToMany(mappedBy = "receiver")
    lateinit var receivedMessages: List<Message>
}

@Entity
class Conversation {

    @Id
    @GeneratedValue
    val id: Long = 0

    @OneToMany(mappedBy = "conversation")
    lateinit var messages: List<Message>
}


@Entity
class Message {

    @Id
    @GeneratedValue
    val id: Long = 0

    @ManyToOne
    lateinit var conversation: Conversation

    @ManyToOne
    lateinit var sender: User

    @ManyToOne
    lateinit var receiver: User

    lateinit var message: String
}

1 个答案:

答案 0 :(得分:0)

您设置的非平凡规则对于Hibernate来说是开箱即用的。

我建议使用DDD聚合和聚合根的概念来分解模型,在聚合内部使用级联并与两者之间的事件进行通信。

我看到两个聚合:UserConversationConversation聚合由Conversation作为聚合根和Message作为附加实体组成。

Message中删除User的列表,并在ConversationRepository中提供查找方法。

您描述的所有逻辑都进入UserUserRepositoryConversationConversationRepository中的方法中。 User*类可以委托给ConversationRepository来操纵ConversationMessage

使用这种方法来实现所需的逻辑应该更容易实现,测试和理解。使用直接SQL而不是JPA可能实际上可以更轻松(甚至更快)地执行许多步骤。当然,您必须注意JPA 1级缓存不会过时。