本文介绍了关于使用@ ForceDiscriminator / @ DiscriminatorOptions(force = true)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述

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

解决方案

当我一遍又一遍地跑过去,我认为这可能会有帮助澄清:
首先,当使用 JOINED_TABLE 映射时,Hibernate确实不需要区分。但是,当使用 SINGLE_TABLE 时,它确实需要它。更重要的是,其他JPA提供者大多需要它。

执行多态 JOINED_TABLE 查询时,Hibernate实际上做了什么是使用case-switch创建一个名为 clazz 的鉴别器,该case-switch用于在外部连接所有涉及继承的表后检查具体子类的唯一字段-树。在 persistence.xml 中包含hibernate.show_sql属性时,您可以清楚地看到这一点。在我看来,这可能是 JOINED_TABLE 查询的完美解决方案,所以Hibernate人员可以对此进行夸耀。



执行更新和删除时,此事有所不同;这里hibernate首先查询你的根表,查找与语句的where子句匹配的任何键,并从结果中创建一个虚拟的 pkTable 。然后它执行一个DELETE FROM / UPDATE table WHERE pk IN pkTable对于具有继承树的任何具体类; IN运算符会扫描每个表项的 O(log(N))子查询,但它很可能在内存中,所以从性能的角度来看它并不算太坏。 / p>

为了回答您的具体问题,Hibernate在这里根本没有看到问题,并且从某种角度来看它们是正确的。通过在 entityManager.persist() @DiscriminatorValue 注释是非常容易的>,即使他们没有真正使用它们。然而,不遵守 JOINED_TABLE 中的鉴别器列的优点是(用于Hibernate)创建一个温和的供应商锁定案例,甚至可以指向优越的技术。



@ForceDiscriminator @DiscriminatorOptions(force = true)确实有助于缓解痛苦,但是必须在创建第一个实体之前使用它们,或者必须使用SQL语句手动添加缺少的鉴别符值。如果你敢从Hibernate中撤出,至少会花费一些代码更改来删除这些Hibernate特定的注释,从而阻碍迁移。根据我的经验,供应商锁定是每个市场领导者最疯狂的梦想所关注的天堂,因为它是马基雅维利安人没有努力保护市场份额的魔杖;因此,只要客户不反击并强迫供应商的价格高于获得的利益,就会这样做。谁说开放源码世界会有所不同?



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



pps:我通常做的是在迁移时间之前忽略问题;您可以使用Hibernate用来填充缺失的鉴别符值的相同case-switch-with-outer-joins技巧来制定一个 SQL UPDATE ... FROM 语句。一旦你理解了基本原理,这其实很简单。


Why is @ForceDiscriminator or its equivalent @DiscriminatorOptions(force=true) necessary in some cases of inheritance and polymorphic associations? It seems to be the only way to get the job done. Are there any reasons not to use it?

解决方案

As I'm running over this again and again, I think it might help to clarify:First, it is true that Hibernate does not require discrimination when using JOINED_TABLE mapping. However, it does require it when using SINGLE_TABLE. Even more importantly, other JPA providers mostly do require it.

What Hibernate actually does when performing a polymorphic JOINED_TABLE query is to create a discriminator named clazz on the fly, using a case-switch that checks for the presence of fields unique for concrete subclasses after outer-joining all tables involved in the inheritance-tree. You can clearly see this when including the "hibernate.show_sql" property in your persistence.xml. In my view this is probably the perfect solution for JOINED_TABLE queries, so the Hibernate folks are right to brag about it.

The matter is somewhat different when performing updates and deletes; here hibernate first queries your root-table for any keys that match the statement's where clause, and creates a virtual pkTable from the result. Then it performs a "DELETE FROM / UPDATE table WHERE pk IN pkTable" for any concrete class withing your inheritance tree; the IN operator causes an O(log(N)) subquery per table entry scanned, but it is likely in-memory, so it's not too bad from a performance perspective.

To answer your specific question, Hibernate simply doesn't see a problem here, and from a certain perspective they are correct. It would be incredibly easy for them to simply honour the @DiscriminatorValue annotations by injecting the discriminator values during entityManager.persist(), even if they do not actually use them. However, not honoring the discriminator column in JOINED_TABLE has the advantage (for Hibernate) to create a mild case of vendor lockin, and it is even defensible by pointing to superior technology.

@ForceDiscriminator or @DiscriminatorOptions(force=true) sure help to mitigate the pain a little, but you have to use them before the first entities are created, or be forced to manually add the missing discriminator values using SQL statements. If you dare to move away from Hibernate it at least costs you some code change to remove these Hibernate specific annotations, creating resistance against the migration. And that is obviously all that Hibernate cares about in this case.

In my experience, vendor lockin is the paradise every market leader's wildest dreams are about, because it is the machiavellian magic wand that protects market share without effort; it is therefore done whenever customers do not fight back and force a price upon the vendor that is higher than the benefits reaped. Who said that an Open Source world would be any different?

p.s, just to avoid any confusion: I am in no way affiliated to any JPA implementor.

p.p.s: What I usually do is ignore the problem until migration time; you can then formulate an SQL UPDATE ... FROM statement using the same case-switch-with-outer-joins trick Hibernate uses to fill in the missing discriminator values. It's actually quite easy once you have understood the basic principle.

这篇关于关于使用@ ForceDiscriminator / @ DiscriminatorOptions(force = true)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 00:29