Что такое естественный идентификатор в Hibernate? - PullRequest
18 голосов
/ 15 декабря 2009

Читая документацию по Hibernate, я постоянно вижу ссылки на концепцию естественного идентификатора .

Означает ли это просто идентификатор, который сущность имеет из-за характера данных, которые она содержит?

например. Имя пользователя + пароль + возраст + что-то используются в качестве составного идентификатора?

Ответы [ 7 ]

19 голосов
/ 13 мая 2014

В Hibernate, натруальные ключи часто используются для поиска. В большинстве случаев у вас будет автоматически суррогатный идентификатор. Но этот идентификатор довольно бесполезен для поиска, так как вы всегда будете запрашивать по полям, таким как имя, номер социального страхования или что-либо еще из реального мира.

При использовании функций кэширования Hibernate это различие очень важно: если кэш индексируется по первичному ключу (суррогатному идентификатору), при поиске не будет никакого увеличения производительности. Вот почему вы можете определить набор полей, с которыми вы будете запрашивать базу данных - естественный идентификатор. Затем Hibernate может индексировать данные по вашему естественному ключу и повысить производительность поиска.

См. Это превосходное сообщение в блоге для более подробного объяснения или страницу RedHat для примера файла отображения Hibernate.

8 голосов
/ 15 декабря 2009

Что естественно идентифицирует сущность. Например, мой адрес электронной почты.

Однако длинная строка переменной длины не является идеальным ключом, поэтому вы можете определить суррогатный идентификатор

AKA Натуральный ключ в реляционном дизайне

5 голосов
/ 31 октября 2017

В системе реляционных баз данных, как правило, вы можете иметь два типа простых идентификаторов :

  • Натуральные ключи, которые присваиваются внешними системами и гарантированно являются уникальными
  • Суррогатные ключи, такие как IDENTITY или SEQUENCE , которые назначаются базой данных.

Причина, по которой суррогатные ключи так популярны, заключается в том, что они более компактны (4 байта или 8 байт) по сравнению с натуральным ключом, который очень длинный (например, VIN занимает 17 буквенно-цифровых символов, книга ISBN имеет длину 13 цифр). ).

Теперь, если суррогатный ключ становится первичным ключом, вы можете сделать это, используя аннотацию JPA @Id.

И, если у вас есть сущность, имеющая также Природный Ключ, помимо Суррогатного, вы можете сопоставить его с привязкой к 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);
    }
}

Теперь, учитывая сущность выше, пользователь мог добавить в закладки статью Post, и теперь он хочет ее прочитать. Однако в закладке URL-адрес содержит slug Естественный идентификатор, а не Первичный ключ.

Итак, мы можем получить это, используя Hibernate:

Post post = entityManager.unwrap(Session.class)
.bySimpleNaturalId(Post.class)
.load(slug); 

И 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

Первый запрос необходим для разрешения идентификатора объекта, связанного с предоставленным естественным идентификатором.

Второй запрос необязателен, если объект уже загружен в кэш первого или второго уровня.

Как я объяснил в этой статье , причина первого запроса в том, что Hibernate уже имеет хорошо отлаженную логику для загрузки и связывания сущностей по их идентификатору в контексте постоянства.

Теперь, если вы хотите пропустить запрос идентификатора сущности, вы можете легко аннотировать сущность, используя аннотацию @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);
    }
}

Таким образом, вы можете получить объект Post, даже не обращаясь к базе данных. Круто, правда?

5 голосов
/ 15 декабря 2009

Естественный идентификатор - это то, что используется в реальном мире в качестве идентификатора. Например, номер социального страхования или номер паспорта.

Обычно плохая идея использовать естественные идентификаторы в качестве ключей на уровне персистентности, потому что а) они могут быть изменены вне вашего контроля, и б) они могут оказаться не уникальными из-за ошибки в другом месте, а затем модель данных не может справиться с этим, поэтому ваше приложение взрывается.

2 голосов
/ 15 декабря 2009

Номер социального страхования может быть натуральным идентификатором или, как вы сказали, хешем информации пользователя. Альтернативой является суррогатный ключ , например, Guid / UID.

1 голос
/ 04 ноября 2018

В теории реляционных баз данных отношение может иметь несколько ключей-кандидатов . ключ-кандидат - это набор атрибутов отношения, которые никогда не дублируются в двух строках этого отношения и не могут быть уменьшены путем удаления одного из атрибутов и при этом гарантируют уникальность.

Естественный идентификатор - это ключ-кандидат. Там, где «натуральный» означает, что данные вашего отношения находятся в природе, а не что-то, что вы добавляете, как автоматически сгенерированный ключ. Естественный идентификатор может состоять из одного атрибута. В общем, любой атрибут отношения, который является уникальным и не нулевым, является ключом-кандидатом и может рассматриваться как естественный идентификатор.

В Hibernate эту аннотацию можно использовать просто для обозначения того, что атрибут можно использовать для поиска, который возвращает уникальные результаты, не используя ключ. Это может быть полезно, когда атрибут, который вы обозначаете как естественный идентификатор, более естественен для вас, например, когда фактический ключ генерируется автоматически и вы не хотите использовать его в поисках.

1 голос
/ 18 июля 2018

Естественный идентификатор (также известный как бизнес-ключ): это идентификатор, который означает или представляет что-то в реальной жизни.
Электронная почта или национальный идентификатор для человек
Исбн для Книга
IBAN для Банк Счет

Эта @NaturalId Аннотация используется для указания натурального идентификатора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...