mysql - Hibernate:在删除父集合时不删除子集合

标签 mysql spring hibernate

我遇到了一个让你咆哮的奇怪问题。我有(也很奇怪)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_viewarchive_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/

相关文章:

spring - Spring 的切入点

java - Hibernate 不会完全刷新实体子项

java - 如何在使用 Hibernate 时删除 Ehcache WARN 消息

php - 通过ajax创建的post变量

php - 数据库架构

java - eclipse中的Spring Boot应用程序,配置为监听端口XXXX的Tomcat连接器启动失败

spring - 在 Spring 应用程序中使用 Repository 还是 Entity manager 更好?

mysql - LIMIT 显示不同的表字段

configuration - MySQL 服务器的 thread_stack 参数 - 它是什么?它应该有多大?

java - 使用 MYSQL 表结构创建 JPA 映射时遇到问题