这是Hibernate official tutorial:
还有一个替代
<composite-id>
声明,允许使用复合键访问旧数据。强烈建议不要使用它。
为什么不鼓励使用复合键?我正在考虑使用一个3列表,其中所有列都是外键,并且一起形成一个主键,在我的模型中是一个有意义的关系。我不明白为什么这是一个坏主意,特别是我会在它们上使用索引。
有什么替代方案?创建一个额外的自动生成列并将其用作主键?我仍然需要查询我的3列!?
简而言之,为什么这句话是真的?什么是更好的选择?
答案 0 :(得分:43)
他们劝阻他们有几个原因:
除了其他三列之外,另一种方法是使用单列自动生成的主键。如果要使三列的元组唯一,则使用唯一约束。
答案 1 :(得分:37)
即使是 - 也许 - 回答你的问题为时已晚,我想在这里提出另一种观点(我希望更温和一点)Hibernate使用代理键的需要(这真的是建议吗?)。
首先,我想清楚两个代理键(人工自动生成的)和自然键(由列组成)具有域意义)具有专业和缺点。我并不是说一个关键类型比另一个更好。我想说,根据您的要求,自然键可能是比代理键更好的选择,反之亦然。
代理键是:
如 Java Persistence with Hibernate 参考:
中所述更有经验的Hibernate用户专门使用saveOrUpdate();它的 更容易让Hibernate决定什么是新的,什么是旧的, 特别是在具有混合状态的更复杂的对象网络中。该 只有(不是很严重)独有的saveOrUpdate()的缺点是 它有时无法猜测实例是旧的还是新的 不在数据库中触发SELECT - 例如,当一个类是 使用自然复合键映射,没有版本或时间戳 属性。
限制的一些表现形式(我认为应该如何调用它)可以找到here。
请不要对你的意见过于平庸。在相关时使用自然键,并在最好使用时使用代理键。
希望这有助于某人!
答案 2 :(得分:10)
我会从设计的角度考虑问题。这不仅仅是因为Hibernate认为它们好坏。真正的问题是:是自然键,是我数据的良好标识符的好选择吗?
在您的商业模式中,今天通过某些数据识别记录会很方便,但商业模式会随着时间的推移而发展。当发生这种情况时,您会发现您的自然键不再适合唯一标识您的数据。并且在其他表格中使用引用完整性,这将使 MUCH 更难以改变。
拥有代理PK很方便,因为它不会如何使用您的业务模型结构链接您的存储中的数据。
无法从序列中生成自然键,并且无法通过其数据识别的数据的情况更多更频繁。这证明自然密钥与存储密钥不同,并且它们不能被视为一般(和良好)方法。
使用代理键简化了应用程序和数据库的设计。它们更易于使用,性能更高,并且可以完美地完成工作。
自然键只带来缺点:我无法想到使用自然键的单一优势。
那就是说,我认为hibernate对自然(组合)键没有实际问题。但是你有时可能会发现一些问题(或错误),以及文档问题或试图获得帮助,因为hibernate社区广泛承认代理键的好处。因此,为为什么选择复合键准备一个很好的答案。
答案 3 :(得分:1)
如果正确理解了Hibernate文档:
&#34;还有一个替代<composite-id>
声明,允许使用复合键访问旧数据。强烈建议不要使用它。&#34;
。 id标记xml <id>
,它使得主键映射过早,我们可以得出结论,hibernate文档不鼓励使用<composite-id>
而不是<id>
xml标记进行复合主键映射和 NOT 使任何参考否定使用复合主键。
答案 4 :(得分:0)
使用聚簇索引进行查询优化,使用数据库作为工具开发的应用程序肯定更有利于保持代理键上的工作流程。
确实需要特别注意数据仓库和OLAP样式系统,它们利用大量的Fact Table将维度的代理键绑定在一起。在这种情况下,数据指示可用于维护记录的仪表板/应用程序。
因此,不是一种方法优于另一种方法,也许一种指令对另一种方法有利,因为关键构造:您不会非常容易地开发Hibernate应用程序来利用对SSAS系统实例的直接访问。
我使用两种关键混合物开发,并且感觉要实现一个坚实的星形或雪花模式,使用聚集索引代理通常是我的首选。
所以,关于OP和其他人的问候:如果你想保持db不变的开发(Hibernate专门研究) - 利用代理方法,当数据读取速度变慢,或者你注意到某些查询会消耗性能,还原到您的特定数据库,并添加优化查询顺序的复合聚簇索引。
答案 5 :(得分:0)
不要混淆主键和唯一索引。如果您使用自然键,则将您的密钥与您的业务、业务数据相关联;它不是那么好。因此,即使可以使用一组数据来定义复合键,也不建议这样做。 在我看来,复合键主要在您拥有现有架构时可用