Рубрики
Без рубрики

Когда JPA устанавливает основной ключ

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

Автор оригинала: baeldung.

Когда JPA устанавливает основной ключ

1. Обзор

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

2. Заявление о проблеме

Как известно, JPA (Java Persistence API) использует EntityManager для управления жизненным циклом Организация . В какой-то момент поставщику JPA необходимо присвоить значение первичному ключу. Итак, мы можем спросить, когда это произойдет? И где документация, в которой говорится об этом?

Спецификация JPA гласит:

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

Итак, мы сосредоточимся на EntityManager.persist () метод в этой статье.

3. Стратегия создания стоимости

Когда мы ссылаемся на EntityManager.persist () метод, состояние сущности изменено в соответствии со спецификацией JPA:

Это означает, что существуют различные способы создания основного ключа. Как правило, существует два решения:

  • Предварительное распределение основного ключа
  • Выделение основного ключа после хискоревания в базе данных
  • ПоколениеType.AUTO
  • ПоколениеType.IDENTITY
  • ПоколениеType.SEQUENCE
  • ПоколениеType.Table

3.1. ПоколениеType.AUTO

АВТО является стратегия по умолчанию для @GeneratedValue . Если мы просто хотим иметь основной ключ, мы можем использовать АВТО стратегия. Поставщик JPA выберет соответствующую стратегию для базовой базы данных:

@Entity
@Table(name = "app_admin")
public class Admin {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "admin_name")
    private String name;

    // standard getters and setters
}

3.2. ПоколениеType.IDENTITY

ИЕ УДОСТОВЕРЕНИЕ стратегия опирается на колонку автоматического приращения базы данных . База данных генерирует основной ключ после каждой операции вставки. JPA присваивает основное ключевое значение после выполнения операции вставки или при коммите транзакции:

@Entity
@Table(name = "app_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "user_name")
    private String name;

    // standard getters and setters
}

Здесь мы проверяем id значения до и после совершения транзакции:

@Test
public void givenIdentityStrategy_whenCommitTransction_thenReturnPrimaryKey() {
    User user = new User();
    user.setName("TestName");
        
    entityManager.getTransaction().begin();
    entityManager.persist(user);
    Assert.assertNull(user.getId());
    entityManager.getTransaction().commit();

    Long expectPrimaryKey = 1L;
    Assert.assertEquals(expectPrimaryKey, user.getId());
}

ИЕ УДОСТОВЕРЕНИЕ Стратегия поддерживается MyS’L, сервером S’L, PostgreS’L, DB2, Derby и Sybase.

3.3. ПоколениеType.SEQUENCE

Используя ПОСЛЕДОВАТЕЛЬНОСТЬ стратегия, JPA генерирует основной ключ с помощью последовательности базы данных . Сначала нам нужно создать последовательность на стороне базы данных, прежде чем применять эту стратегию:

CREATE SEQUENCE article_seq
  MINVALUE 1
  START WITH 50
  INCREMENT BY 50

JPA устанавливает основные ключевые после того, как мы вызовем EntityManager.persist () метод и перед совершением транзакции .

Давайте определим Статья сущность с ПОСЛЕДОВАТЕЛЬНОСТЬ стратегия:

@Entity
@Table(name = "article")
public class Article {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "article_gen")
    @SequenceGenerator(name="article_gen", sequenceName="article_seq")
    private Long id;

    @Column(name = "article_name")
    private String name

    // standard getters and setters
}

Последовательность начинается от 50, так что первый id будет следующее значение, 51.

Теперь давайте ПОСЛЕДОВАТЕЛЬНОСТЬ стратегия:

@Test
public void givenSequenceStrategy_whenPersist_thenReturnPrimaryKey() {
    Article article = new Article();
    article.setName("Test Name");

    entityManager.getTransaction().begin();
    entityManager.persist(article);
    Long expectPrimaryKey = 51L;
    Assert.assertEquals(expectPrimaryKey, article.getId());

    entityManager.getTransaction().commit();
}

ПОСЛЕДОВАТЕЛЬНОСТЬ стратегия поддерживается Oracle, PostgreS’L и DB2.

3.4. ПоколениеType.TABLE

ТАБЛИЦА стратегия генерирует основной ключ из таблицы и работает одинаково независимо от базовой базы данных.

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

Во-первых, давайте создадим таблицу генераторов:

@Table(name = "id_gen")
@Entity
public class IdGenerator {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "gen_name")
    private String gen_name;

    @Column(name = "gen_value")
    private Long gen_value;

    // standard getters and setters
}

Затем нам нужно вставить два исходных значения в таблицу генератора:

INSERT INTO id_gen (gen_name, gen_val) VALUES ('id_generator', 0);
INSERT INTO id_gen (gen_name, gen_val) VALUES ('task_gen', 10000);

JPA присваивает основные ключевые значения после вызова EntityManager.persist() метод и до совершения транзакции.

Давайте теперь использовать таблицу генератора с ТАБЛИЦА стратегия. Мы можем использовать распределениеСейные предварительно выделить некоторые основные клавиши:

@Entity
@Table(name = "task")
public class Task {
    
    @TableGenerator(name = "id_generator", table = "id_gen", pkColumnName = "gen_name", valueColumnName = "gen_value",
        pkColumnValue="task_gen", initialValue=10000, allocationSize=10)
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "id_generator")
    private Long id;

    @Column(name = "name")
    private String name;

    // standard getters and setters
}

И id начинается от 10 000 после того, как мы ссылаемся на сохраняются метод:

@Test
public void givenTableStrategy_whenPersist_thenReturnPrimaryKey() {
    Task task = new Task();
    task.setName("Test Task");

    entityManager.getTransaction().begin();
    entityManager.persist(task);
    Long expectPrimaryKey = 10000L;
    Assert.assertEquals(expectPrimaryKey, task.getId());

    entityManager.getTransaction().commit();
}

4. Заключение

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

Полный код можно найти более на GitHub .