java Hibernate 中的自然标识符是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1910220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is a natural identifier in Hibernate?
提问by benstpierre
While reading through the Hibernate documentation, I keep seeing references to the concept of a natural identifier.
在阅读 Hibernate 文档时,我不断看到对自然标识符概念的引用。
Does this just mean the id an entity has due to the nature of the data it holds?
这是否仅意味着实体由于其持有的数据的性质而具有的 id?
E.g. A user's name + password + age + something are used as a compound identitifier?
例如,用户名 + 密码 + 年龄 + 某物被用作复合标识符?
回答by chris
In Hibernate, natrual keys are often used for lookups. You will have an auto-generated surrogate id in most cases. But this id is rather useless for lookups, as you'll always query by fields like name, social security number or anything else from the real world.
在 Hibernate 中,自然键通常用于查找。在大多数情况下,您将拥有一个自动生成的代理 ID。但是这个 id 对查找毫无用处,因为您总是会按姓名、社会保险号或其他任何来自现实世界的字段进行查询。
When using Hibernate's caching features, this difference is very important: If the cache is indexed by your primary key (surrogate id), there won't be any performance gain on lookups. That's why you can define a set of fields that you are going to query the database with - the natural id. Hibernate can then index the data by your natural key and improve the lookup performance.
当使用 Hibernate 的缓存特性时,这个区别非常重要:如果缓存是由你的主键(代理 ID)索引的,那么查找时不会有任何性能提升。这就是为什么您可以定义一组字段,您将使用这些字段来查询数据库 - 自然 id。Hibernate 然后可以通过您的自然键索引数据并提高查找性能。
See this excellent blog postfor a more detailed explanation or this RedHat pagefor an example Hibernate mapping file.
回答by Vlad Mihalcea
Since this is a very common question, I wrote this article, on which this answer is based on.
由于这是一个非常常见的问题,我写了 这篇文章,这个答案是基于它的。
In a relational database system, typically, you can have two types of simple identifiers:
在关系数据库系统中,通常可以有两种类型的简单标识符:
- Natural keys, which are assigned by external systems and guaranteed to be unique
- Surrogate keys, like IDENTITY or SEQUENCEwhich are assigned by the database.
- 自然键,由外部系统分配并保证唯一
- 代理键,例如由数据库分配的IDENTITY 或 SEQUENCE。
The reason why Surrogate Keys are so popular is that they are more compact (4 bytes or 8 bytes), compared to a Natural Key which is very long (e.g. the VIN takes 17 alphanumerical characters, the book ISBN is 13 digits long). If the Surrogate Key becomes the Primary Key, you can map it using the JPA @Idannotation.
Surrogate Keys 如此受欢迎的原因是它们更紧凑(4 字节或 8 字节),与非常长的自然密钥相比(例如,VIN 需要 17 个字母数字字符,书籍 ISBN 是 13 位数字长)。如果代理键成为主键,您可以使用 JPA@Id注释映射它。
Now, let's assume we have the following Postentity:
现在,让我们假设我们有以下Post实体:
Since the Postentity that has also a Natural Key, besides the Surrogate one, you can map it with the Hibernate-specific @NaturalIdannotation:
由于Post实体也有一个自然键,除了代理一个,你可以用 Hibernate 特定的@NaturalId注释来映射它:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@NaturalId
@Column(nullable = false, unique = true)
private String slug;
//Getters and setters omitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
Post post = (Post) o;
return Objects.equals(slug, post.slug);
}
@Override
public int hashCode() {
return Objects.hash(slug);
}
}
Now, considering the entity above, the user might have bookmarked a Postarticle and now they want to read it. However, the bookmarked URL contains the slugNatural Identifier, not the Primary Key.
现在,考虑到上面的实体,用户可能已经为Post一篇文章添加了书签,现在他们想要阅读它。但是,添加书签的 URL 包含slug自然标识符,而不是主键。
So, we can fetch it like this using Hibernate:
因此,我们可以使用 Hibernate 像这样获取它:
Post post = entityManager.unwrap(Session.class)
.bySimpleNaturalId(Post.class)
.load(slug);
And Hibernate will execute the following two queries:
而 Hibernate 将执行以下两个查询:
SELECT p.id AS id1_0_
FROM post p
WHERE p.slug = 'high-performance-java-persistence'
SELECT p.id AS id1_0_0_,
p.slug AS slug2_0_0_,
p.title AS title3_0_0_
FROM post p
WHERE p.id = 1
The first query is needed to resolve the entity identifier associated with the provided natural identifier.
需要第一个查询来解析与提供的自然标识符关联的实体标识符。
The second query is optional if the entity is already loaded in the first or the second-level cache.
如果实体已加载到一级或二级缓存中,则第二个查询是可选的。
As I explained in this article, the reason for having the first query is because Hibernate already has a well-established logic for loading and associating entities by their identifier in the Persistence Context.
正如我在本文中解释的那样,进行第一个查询的原因是因为 Hibernate 已经有一个完善的逻辑,用于通过持久性上下文中的标识符加载和关联实体。
Now, if you want to skip the entity identifier query, you can easily annotate the entity using the @NaturalIdCacheannotation:
现在,如果您想跳过实体标识符查询,您可以使用@NaturalIdCache注释轻松地对实体进行注释:
@Entity(name = "Post")
@Table(name = "post")
@org.hibernate.annotations.Cache(
usage = CacheConcurrencyStrategy.READ_WRITE
)
@NaturalIdCache
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@NaturalId
@Column(nullable = false, unique = true)
private String slug;
//Getters and setters omitted for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass())
return false;
Post post = (Post) o;
return Objects.equals(slug, post.slug);
}
@Override
public int hashCode() {
return Objects.hash(slug);
}
}
This way, you can fetch the Postentity without even hitting the database. Cool, right?
这样,您Post甚至可以在不访问数据库的情况下获取实体。酷,对吧?
回答by gbn
What naturally identifies an entity. For example, my email address.
什么自然地标识了一个实体。例如,我的电子邮件地址。
However, a long variable length string is not an ideal key, so you may want to define a surrogate id
但是,长的可变长度字符串不是理想的键,因此您可能需要定义一个代理 id
AKA Natural keyin relational design
AKA关系设计中的自然键
回答by Mark Byers
A natural identifier is something that is used in the real world as an identifier. An example is a social security number, or a passport number.
自然标识符是在现实世界中用作标识符的东西。一个例子是社会安全号码或护照号码。
It is usually a bad idea to use natural identifiers as keys in a persistence layer because a) they can be changed outside of your control, and b) they can end up not being unique due to a mistake elsewhere, and then your data model can't handle it so your application blows up.
在持久层中使用自然标识符作为键通常是一个坏主意,因为 a) 它们可以在您的控制之外进行更改,并且 b) 由于其他地方的错误,它们最终可能不是唯一的,然后您的数据模型可以不处理它所以你的应用程序爆炸。
回答by user1708042
In relational database theory a relation can have multiple candidate keys. A candidate keyis a set of attributes of a relation that are never duplicate in two rows of that relation and that cannot be reduced by removing one of the attributes and still guarantee uniqueness.
在关系数据库理论中,一个关系可以有多个候选键。一个候选键是一组从来没有在这种关系的两排和复制关系的属性不能去除的属性之一,仍然保证唯一性降低。
A natural ID is essentially a candidate key. Where "natural" means it is in the nature of the data you hold in that relation, not something you add like an autogenerated key. A natural ID can be composed of a single attribute. In general any attribute of a relation that is unique and not-null is a candidate key, and can be considered a natural id.
自然 ID 本质上是一个候选键。“自然”意味着它是您在该关系中保存的数据的性质,而不是您添加的诸如自动生成的密钥之类的东西。自然 ID 可以由单个属性组成。通常,关系的任何唯一且非空的属性都是候选键,并且可以被视为自然 id。
In Hibernate this annotation can be used simply to denote that an attribute can be used to do searches that return unique results while not using the key. This can be useful when the attribute you denote as natural id is more natural to deal with for you, e.g. when the actual key is autogenerated and you don't want to use in searches.
在 Hibernate 中,这个注解可以简单地用来表示一个属性可以用来进行搜索,在不使用键的情况下返回唯一的结果。当您表示为自然 id 的属性对您来说处理起来更自然时,这会很有用,例如,当实际的键是自动生成的并且您不想在搜索中使用时。
回答by Chris S
A social security number might be a natural identity, or as you've said a hash of the User's information. The alternative is a surrogate key, for example a Guid/UID.
回答by Ahmad Al-Kurdi
Natural identifier(also known as business key): is an identifier that means or represent something in real life.
Emailor national idfor person
Isbnfor Book
IBANfor Bankaccount
自然标识符(也称为业务密钥):是表示或代表现实生活中的事物的标识符。
电子邮件或身的人
书号的书
IBAN的银行帐户
This @NaturalIdAnnotation is used to specify Natural identifier.
该@NaturalId注解用于指定自然标识符。


