Когда 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 .