我遇到了一个让你咆哮的奇怪问题。我有(也很奇怪)Spring/Hibernate 应用程序,旨在以以下方式管理数据库(我简化了一些事情,所以不要对源代码提到的稍微不同的表/列感到困惑):
active_proxy_view table:
id | entity
<uuid> | <string containing json>
archive_proxy_view table:
id | entity
<uuid> | <string containing json>
track_reference table:
ref_type | ref_id | track_domain | track_type | track_id |
'proxy' | <uuid> | 'example.com' | 'customer' | '123' |
保留两个表是强制性的 - 我需要仅针对当前处于事件状态的事物进行所有时间历史记录/统计查询和业务值(value)查询,因此我需要保持事件代理的设置紧密。 track_reference
表用于搜索,因此我可以执行这样的查询:
SELECT p.id, p.entity FROM archive_proxy_view AS p
INNER JOIN track_reference AS t1 ON
t1.ref_id = p.id AND
t1.ref_type = 'proxy' AND
t1.track_domain = 'example.com' AND
t1.track_type = 'customer' AND
t1.track_id = '123'
INNER JOIN track_reference AS t2 ON
t2.ref_id = p.id AND
t2.ref_type = 'proxy' AND
t2.track_domain = 'example.com' AND
t2.track_type = 'campaign' AND
t2.track_id = 'halloween-2017'
(可能不是100%正确,我已经有一段时间没有原始的sql经验了)
问题是这样的:
active_proxy_view
和archive_proxy_view
实体均继承自一个在track_reference
实体上指定@OneToMany
关系的类;@ManyToOne
用法实际上是不可能的,因为有许多实体与跟踪引用相关track_reference
单独管理(这也是强制性的)- 我需要与
track_reference
表分开管理 View ,但是每当我告诉 Hibernate 从active_proxy_view
表中删除实体时,它就会删除track_reference
实体也是如此。即使我使用级联注释值,默认情况下该值是空白的(据我所知,这意味着子记录不应与父记录一起删除)。不过,我可能错过了一些东西。 我也未能使用自定义
@SQLDeleteAll
破解整个事情,我仍然可以在常规日志中看到常规删除:55 Query delete from tracking_reference where referenced_entity_id='13c6b55c-f9b7-4de7-8bd4-958d487e461c' and referenced_entity_type='proxy' and tracked_entity_type='agent' 55 Query delete from tracking_reference where referenced_entity_id='13c6b55c-f9b7-4de7-8bd4-958d487e461c' and referenced_entity_type='proxy' and tracked_entity_type='lead' 55 Query delete from tracking_reference where referenced_entity_id='13c6b55c-f9b7-4de7-8bd4-958d487e461c' and referenced_entity_type='proxy' and tracked_entity_type='source' 53 Query DELETE FROM `tracking_reference` WHERE `referenced_entity_type` = 'proxy' AND referenced_entity_id = '13c6b55c-f9b7-4de7-8bd4-958d487e461c' AND 1 = 0
我使用的是 Hibernate 5.2.3.Final 到 Spring 4.3.2.RELEASE/Spring Data JPA 1.10.2.RELEASE
TL;博士
所以,问题是:当父级被删除时,如何防止 Hibernate 删除关联实体?
实体的源代码如下所示:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class ProxyViewEntryTemplate {
@Id
@NotNull
@Column(nullable = false)
private String id;
@NotNull
@Column
private String entity;
// some other columns
@OneToMany
@JoinColumn(name = TrackRef.REFERENCE_ID_COLUMN_NAME) // 'reference_entity_id`
@Where(clause = ProxyView.TRACK_WHERE_JOIN_CLAUSE) // `referenced_entity_type` = 'proxy'
@SQLDeleteAll(sql = ProxyView.TRACK_DELETE_ALL_QUERY) // DELETE FROM `tracking_reference` WHERE `referenced_entity_type` = 'proxy' AND referenced_entity_id = ? AND 1 = 0
private Collection<TrackingReference> track = new ArrayList<>();
// setters, getters, hashCode, equals
}
@Entity
@Table(name = "active_proxy")
public class ActiveProxyViewEntry extends ProxyViewEntryTemplate {}
@Entity
@Table(name = "tracking_reference")
@IdClass(TrackingReferenceId.class)
public class TrackingReference {
@Id
@Column(name = "tracked_entity_type", nullable = false)
@NotNull
private String trackedType;
@Id
@Column(name = "tracked_entity_domain", nullable = false)
private String trackedDomain;
@Id
@Column(name = "tracked_entity_id", nullable = false)
private String trackedId;
@Id
@Column(name = "referenced_entity_type", nullable = false)
@NotNull
private String referencedType;
@Id
@Column(name = "referenced_entity_id", nullable = false)
@NotNull
private String referencedId;
// setters, getters, hashCode, equals
}
整个事情是通过 Spring JPA 存储库进行管理的:
@NoRepositoryBean
public interface SuperRepository<E, ID extends Serializable> extends PagingAndSortingRepository<E, ID>,
JpaSpecificationExecutor<E> {
}
public interface ActiveProxyViewRepository extends SuperRepository<ActiveProxyViewEntry, String> {}
// the call for deletion
public CompletableFuture<Void> delete(ID id) {
...
descriptor.getRepository().delete(descriptor.getIdentifierConverter().convert(id));
...
}
// which is equal to
...
ActiveProxyViewRepository repository = descriptor.getRepository();
String uuidAsString = descriptor.getIdentifierConverter().convert(id);
repository.delete(uuidAsString);
...
最佳答案
如果删除@JoinColumn
,则不会出现此问题。
如果您需要保留@JoinColumn
,则需要通过将注释更改为以下内容来删除持久性提供程序自动应用的外键约束要求:
@JoinColumn(
name = "yourName"
foreignKey = @Foreignkey(value = ConstraintMode.NO_CONSTRAINT)
)
然后您应该能够删除 View 实体,而无需强制删除跟踪引用。
关于mysql - Hibernate:在删除父集合时不删除子集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42118845/