【问题标题】:JPA+Hiberante how to delete entities on multiple dependenciesJPA + Hibernate如何删除多个依赖项上的条目
【发布时间】:2023-03-24 08:35:02
【问题描述】:

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

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

在我看来,我可以在任何地方设置除 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
}

【问题讨论】:

  • 一个建议是不要对多个关系字段使用列表类型。它会导致笛卡尔结果。
  • 你的意思是没有例如同时在对话和用户中列出消息?
  • 我的意思是不要将它们全部映射为User 实体中的列表conversations、sentMessages、receivedMessages。看看:stackoverflow.com/questions/6562673/…
  • 谢谢!我重新设计了我的实体。

标签: hibernate jpa spring-data-jpa


【解决方案1】:

您设置的重要规则太多,Hibernate 无法立即处理。

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

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

从User 中删除Messages 列表,并在ConversationRepository 中提供finder-methods。

您描述的所有逻辑都包含在User、UserRepository、Conversation 和ConversationRepository 中的方法中。 User* 类可以委托给ConversationRepository 来操作Conversations 和Messages。

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

【讨论】:

  • 谢谢!所以这个逻辑太复杂了,不能用hibernate来实现,我必须在我的业务逻辑的某个地方实现它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
  • 2018-08-11
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
相关资源
最近更新 更多