Hibernate不会删除OneTo复合键中的父实体,而是删除键和实体
我有两个主要实体:Hibernate不会删除OneTo复合键中的父实体,而是删除键和实体,hibernate,jpa,Hibernate,Jpa,我有两个主要实体:Client和Bundle。他们有一个双向的多人关系,正如预期的那样。示例: 客户机有几个包。我删除了客户端。所有捆绑包实体都会随着该客户端的删除而更新,但捆绑包实体仍会保留 我更新客户机并从其集中删除捆绑包。同一个捆绑包的集将随着客户端的删除而更新。bundle实体将保留 所有这些都是双向的 Client和Bundle都与实体clientbundleaproval有一个OneToMany关系,作为复合键。它还有一个枚举(已批准、已拒绝、待定) 我的问题是:假设我配置了多个实体
Client
和Bundle
。他们有一个双向的多人关系,正如预期的那样。示例:
集中删除捆绑包。同一个捆绑包的集将随着客户端的删除而更新。bundle实体将保留
Client
和Bundle
都与实体clientbundleaproval
有一个OneToMany关系,作为复合键。它还有一个枚举(已批准、已拒绝、待定)
我的问题是:假设我配置了多个实体。一个客户有几个捆绑包,还有几个待批准的包。当我试图删除客户端时,如果存在一行具有复合键,并且该行包含在ClientBundleApproval
中,则该客户端将不会被删除
我的预期结果是,ClientBundleApproval
中包含该客户ID的所有行都将被删除,所有bundle都将删除其相关批准的集合,并更新客户机(基本上是级联删除,但仅针对复合键表,而不针对其他实体)。添加级联删除会导致删除客户机删除复合密钥,但也会删除捆绑包(这不是所需的行为)
我需要帮助确定我的配置是否有问题,或者这是不可能的。我假设可能应该首先删除组合键行,但我需要将处理这些实体的服务的逻辑保持分离。(例如,在ClientService
中,不必注入其他实体的JpaRepository
)
实现说明:我正在使用Spring JPA,因此对于每个实体,我都有一个扩展Spring的JpaRepository
的接口,我将其注入服务类,并使用它而不是EntityManager
执行CRUD操作
我已经尝试过从OneToMany、不同类型的级联(在关系声明中和使用@cascade
)中删除mappedBy,无论是否删除孤立项。我想不出有什么效果
实体和图表:
客户(我删除了一些样板)
ClientBundleKey
@jenschauder我不确定我是否能理解这个答案对我有什么帮助。我的两个实体
Client
和Bundle
彼此完全独立(Bundle可以没有客户端,反之亦然)。关于ClientBundleApproval
,我从回答中了解到,我不应该为它设置jpappositional
,我应该通过更新客户端来管理此表。对吗?即便如此,我仍然面临着同样的问题。最后一段说明不要直接向客户公开那些JpaRepository
。我不这样做,我在专门的服务室里使用它们来消除混乱。它不是为了解决您当前的问题。但是您提到:“我使用的是Spring JPA,所以对于每个实体,我都有一个扩展Spring的JpaRepository的接口”,这是我链接到的答案中讨论的常见反模式。@maydown hi!我也遇到了同样的问题。你还记得你是怎么修好的吗?
@Entity
@Table(name = "client_details")
public class Client implements Serializable {
@JoinTable(
name = "client_bundle",
joinColumns = { @JoinColumn(name = "client_id") },
inverseJoinColumns = { @JoinColumn(name = "bundleName") }
)
@Column(name = "bundles")
@ManyToMany(fetch = FetchType.EAGER /* all types of cascade except delete */)
private Set<Bundle> clientBundles;
@OneToMany(mappedBy = "client", fetch = FetchType.EAGER, orphanRemoval = true /* all types of cascade except delete */)
private List<ClientBundleApproval> approvals;
}
@Entity
@Table(name = "bundle")
public class Bundle implements Serializable {
@ManyToMany(mappedBy="clientBundles", fetch = FetchType.EAGER /* all types of cascade except delete */)
private Set<Client> clients;
@OneToMany(mappedBy = "bundle", fetch = FetchType.EAGER, orphanRemoval = true /* all types of cascade except delete */)
private List<ClientBundleApproval> approvals;
}
@Entity
@Table(name = "client_bundle_approval")
public class ClientBundleApproval implements Serializable {
@EmbeddedId
private ClientBundleKey clientBundleKey;
@ManyToOne(fetch = FetchType.EAGER /* all types of cascade except delete */)
@JoinColumn(name = "client", referencedColumnName = "id")
@MapsId("clientId")
private Client client;
@ManyToOne(fetch = FetchType.EAGER /* all types of cascade except delete */)
@JoinColumn(name = "bundle", referencedColumnName = "id")
@MapsId("bundleId")
private Bundle bundle;
@Enumerated(EnumType.STRING)
private ClientBundleApprovalStatus approvalStatus;
}
@Embeddable
public class ClientBundleKey implements Serializable{
private String clientId;
private String bundleId;
}