Java 为什么在hibernate中不鼓励使用复合键?
这是来自: 还有一种替代的Java 为什么在hibernate中不鼓励使用复合键?,java,database,hibernate,orm,composite-key,Java,Database,Hibernate,Orm,Composite Key,这是来自: 还有一种替代的声明,允许使用复合键访问遗留数据。强烈反对将其用于任何其他用途 为什么不鼓励使用复合键?我正在考虑使用一个3列表,其中所有列都是外键,共同构成一个主键,这在我的模型中是一个有意义的关系。我不明白为什么这是一个坏主意,特别是我将对它们使用索引 替代方案是什么?创建其他自动生成的列并将其用作主键?我仍然需要查询我的3列 简言之,为什么这一说法是正确的?还有什么更好的选择呢?他们出于以下几个原因不鼓励他们: 它们使用起来很麻烦。每次需要引用对象(或行)时,例如web应用程序
声明,允许使用复合键访问遗留数据。强烈反对将其用于任何其他用途
为什么不鼓励使用复合键?我正在考虑使用一个3列表,其中所有列都是外键,共同构成一个主键,这在我的模型中是一个有意义的关系。我不明白为什么这是一个坏主意,特别是我将对它们使用索引
替代方案是什么?创建其他自动生成的列并将其用作主键?我仍然需要查询我的3列
简言之,为什么这一说法是正确的?还有什么更好的选择呢?他们出于以下几个原因不鼓励他们:
- 它们使用起来很麻烦。每次需要引用对象(或行)时,例如web应用程序中的eexample,都需要传递3个参数,而不仅仅是一个参数
- 他们效率低下。数据库需要散列一个由3列组成的组合,而不是简单地散列一个整数
- 它们会导致错误:开发人员不可避免地错误地实现主键类的equals和hashCode方法。或者使其可变,并在存储在HashSet或HashMap中后修改其值
- 它们污染了模式。如果另一个表需要引用此3列表,则它需要有3列而不是一列作为外键。现在假设您遵循相同的设计,并将此3列外键作为此新表的主键的一部分,您将很快拥有一个4列主键,然后在下一个表中拥有一个5列主键,以此类推,从而导致数据重复和脏模式
另一种选择是,除了其他三列之外,还有一列自动生成的主键。如果要使三列的元组唯一,则使用唯一的约束。< P>我会从设计的角度考虑这个问题。不仅仅是Hibernate认为它们是好是坏。真正的问题是:自然键是我的数据的好标识符吗 在您的业务模型中,现在可以方便地通过记录的一些数据来识别记录,但业务模型会随着时间的推移而变化。当这种情况发生时,您会发现您的自然密钥不再适合唯一地标识您的数据。由于其他表中的引用完整性,这将使事情更难更改 拥有代理PK很方便,因为它不会将存储中的数据标识方式与业务模型结构联系起来 自然密钥不能从序列中生成,并且不能通过其数据识别的数据的情况更为常见。这是自然密钥不同于存储密钥的证据,不能将其视为通用(良好)方法 使用代理键简化了应用程序和数据库的设计。它们更易于使用,性能更高,工作也更出色 自然键只带来缺点:我想不出使用自然键有什么好处
也就是说,我认为hibernate在自然(合成)键方面没有真正的问题。但是您有时可能会发现一些问题(或bug),文档或试图获得帮助时也会遇到问题,因为hibernate社区广泛承认代理键的好处。因此,为您为什么选择复合键准备一个好的答案。即使现在回答您的问题可能已经太晚了,我想在这里就Hibernate使用代理键的必要性(这真的是一个建议吗?)给出另一个观点(我希望更温和) 首先,我想明确一个事实,代理键(人工自动生成的键)和自然键(由具有域含义的列组成)都有优点和缺点。我并不是说一种键类型比另一种更好。我想说的是,根据您的需求,自然键可能是比代理键更好的选择,反之亦然 关于自然钥匙的神话
- 它们通常使用自动递增的列来实现,这意味着:
- 每次您想要获得一个新Id时,都要往返数据库(我知道这可以通过使用缓存或类似[seq]hilo的算法来改进,但这些方法仍有其自身的缺点)
- 如果有一天您需要将数据从一个模式移动到另一个模式(至少在我的公司是这样),那么您可能会遇到Id冲突问题。是的,我知道您可以使用UUID,但这些UUID需要32位十六进制数字!(如果您关心数据库大小,那么这可能是一个问题)
- 如果您对所有代理项密钥使用一个序列,那么-当然-您将在数据库上产生争用<