小编典典

关于@ ForceDiscriminator / @ DiscriminatorOptions(force = true)的使用

hibernate

在继承和多态关联的某些情况下,为什么@ForceDiscriminator或其等效项是@DiscriminatorOptions(force=true)必需的?这似乎是完成工作的唯一方法。有没有理由不使用它?


阅读 637

收藏
2020-06-20

共1个答案

小编典典

当我一次又一次地讨论这个问题时,我认为这可能有助于澄清:首先,的确,使用JOINED_TABLE映射时Hibernate不需要歧视。但是,使用时确实需要它SINGLE_TABLE。更重要的是,其他JPA提供程序也确实需要它。

当执行多态JOINED_TABLE查询时,Hibernate实际要做的是创建一个动态命名的鉴别器clazz,使用一个case开关,在外部连接继承树中涉及的所有表之后,检查具体子类唯一字段的存在。当您在中包含"hibernate.show_sql"属性时,您可以清楚地看到这一点persistence.xml。在我看来,这可能是JOINED_TABLE查询的理想解决方案,因此,Hibernate人士应该吹牛。

执行更新和删除时,此问题有所不同。在这里,hibernate首先在根表中查询与该语句的where子句匹配的任何键,然后pkTable从结果中创建一个虚拟键。然后,它"DELETE FROM / UPDATE table WHERE pk IN pkTable"为继承树的任何具体类执行一个;IN运算符会为O(log(N))每个扫描的表条目导致一个子查询,但它很可能在内存中,因此从性能角度来看还不错。

为了回答您的特定问题,Hibernate在这里根本看不到问题,并且从某种角度讲它们是正确的。对于他们来说,通过简单地@DiscriminatorValue通过在期间注入鉴别符值来兑现注释(entityManager.persist()即使他们实际上并未使用它们)将非常容易。但是,不承认其中的歧视项会JOINED_TABLE(对于Hibernate)具有创建厂商锁定的温和情况的优势,并且通过使用高级技术甚至可以辩护。

@ForceDiscriminator@DiscriminatorOptions(force=true)一定有助于减轻痛苦,但是您必须在创建第一个实体之前使用它们,或者被迫使用SQL语句手动添加缺少的鉴别符值。如果您敢于离开Hibernate,则至少要花费一些代码更改才能删除这些特定于Hibernate的注释,从而抵制迁移。显然,在这种情况下,这就是Hibernate所关心的。

以我的经验,供应商锁定是每个市场领导者最梦wild以求的天堂,因为正是手风琴魔术棒可以毫不费力地保护市场份额。因此,只要客户不进行反击并向卖方强加高于所获收益的价格,便会这样做。谁说开源世界会有所不同?

ps,只是为了避免造成任何混乱:我绝不隶属于任何JPA实现者。

pps:我通常要做的是忽略问题,直到迁移时间为止。然后,您可以SQL UPDATE ... FROM使用Hibernate用来填充缺失的鉴别符值的相同case-switch-with-outer-
joins技巧来制定一条语句。一旦了解了基本原理,实际上就很容易了。

2020-06-20