Первичный ключ

Модуль 4. Работа с БД
12 уровень , 2 лекция
Открыта

Аннотация @Id

Каждая Entity-сущность в Hibernate должна иметь поле, которое будет первичным ключом: содержать уникальное значение для всех объектов данного класса. Обычно это поле помечается аннотацией @Id.

Общий вид:


   @Id
   Класс имя;

Пример:


@Entity
@Table(name="user")
class User
{
   @Id
   @Column(name="id")
   public Integer id;
 
   @Embedded
   public UserAddress address;
 
   @Column(name="created_date")
   public Date createdDate;
}

Размещение аннотаций

Кстати, ты можешь писать аннотации @Column не только у полей, но и методов: у геттеров или сеттеров. Пример:


@Entity
@Table(name="user")
class User
{
    public Integer id;
    public Date createdDate;
 
   @Id
   @Column(name="id")
   public Integer getId() {
   	return this.id;
   }
   public void setId(Integer id)    {
  	this.id = id;
   }
 
   @Column(name="created_date")
   public Date getCreatedDate() {
  	return this.createdDate;
   }
   public void setCreatedDate(Date date) {
      this.createdDate = date;
   }
}

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

Важно! Если у класса есть аннотация @Entity, то все его поля рассматриваются Hibernate как сохраняемые поля (если у них не указана аннотация @Transient). Даже если у полей нет вообще никаких аннотаций: при этом имя колонки считается равным имени поля класса.

И тут аннотация @Id играет важную роль. Если аннотация размещена у поля класса, то Hibernate будет смотреть на имена и типы полей. Если аннотация @Id размещена у метода, тогда Hibernate будет смотреть на имена и типы методов.

Пример 1:


@Entity
@Table(name="user")
class User
{
   @Id
    public Integer id;
    public Date createdDate;  //это поле будет обработано как будто тут есть @Column(name="createdDate")
 
}

Пример 2:


@Entity
@Table(name="user")
class User
{
    public Integer id;
    public Date createdDate;  
 
   @Id
   public Integer getId() {
   	return this.id;
   }
   public void setId(Integer id)    {
  	this.id = id;
   }
 
   public Date getCreatedDate() { //это поле будет обработано как будто тут есть @Column(name="createdDate")
  	return this.createdDate;
   }
   public void setCreatedDate(Date date) {
  	this.createdDate = date;
   }
 
}

Аннотация @GeneratedValue

Ты можешь присваивать id твоим новым объектам самостоятельно, или отдать это на откуп Hibernate. Для того чтобы Hibernate лучше понимал, как присваивать ID твоим объектам, у него есть специальная аннотация:


@GeneratedValue

Этой аннотацией обычно помечается то же поле, что и аннотацией @Id. У нее есть 4 возможных стратегии присвоения ID:

  • AUTO
  • IDENTITY
  • SEQUENCE
  • TABLE

Пример аннотации с указанной стратегией:


@Entity
@Table(name="user")
class User
{
    @Id
	@GeneratedValue(strategy = GenerationType.AUTO)
    public Integer id;
 
    public Date createdDate;
}

Если значение стратегии не указано, то выберется стратегия AUTO. Стратегия AUTO означает, что Hibernate будет сам назначать ID, основываясь в первую очередь на типе данных у поля ID.

Почему именно на типе? Да потому, что типы у ID могут быть очень разные, например, String или GUID. Пример:


@Entity
@Table(name="user")
class User
{
    @Id
	@GeneratedValue
    public UUID id;
 
    public Date createdDate;
}

Примечание: GUID в Java называется UUID, так исторически пошло. И Hibernate умеет генерировать уникальные UUID для твоих объектов, если ты его об этом попросишь.

Различные стратегии @GeneratedValue

Если ты укажешь тип GeneratedValue(strategy = GenerationType.IDENTITY), то Hibernate делегирует установку ID на уровень базы данных. Обычно при этом используется колонка, помеченная как PRIMARY KEY, AUTOINCREMENT.

А вот если ты хочешь, чтобы твои ID были уникальными и генерировались по специально заданному алгоритму, то можешь воспользоваться аннотацией GeneratedValue(strategy = GenerationType.SEQUENCE), пример:


@Entity
@Table(name="user")
public class User {
	@Id
	@GeneratedValue(generator = "sequence-generator")
	@GenericGenerator(
  	name = "sequence-generator",
  	strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
  	parameters = {
    	@Parameter(name = "sequence_name", value = "user_sequence"),
    	@Parameter(name = "initial_value", value = "4"),
    	@Parameter(name = "increment_size", value = "1")
    	}
	)
	private long userId;
	
	// ...
}

Есть еще много разных способов генерации ID. Например, у тебя может быть составной уникальный ключ, состоящий из нескольких колонок. И при записи объекта в базу, нужно все эти колонки заполнить.

Я не буду их подробно приводить. Все-таки задача наших лекций – это знакомство с Hibernate, а не пересказ официальной документации.

Комментарии (9)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Мая Уровень 82
1 ноября 2025
Помощь от ИИ : "GenerationType.SEQUENCE работает, используя отдельную последовательность (sequence) в базе данных для генерации уникальных значений для первичного ключа. При необходимости получить новое значение, приложение запрашивает его у этой последовательности, которая затем возвращает следующий уникальный номер. Эта стратегия обеспечивает независимость генерации ключей от самой таблицы. Генерация ключа происходит вне таблицы, что может быть полезно, особенно при работе с большими таблицами или в сценариях с высокой конкуренцией."
Дмитрий Уровень 37
17 марта 2024
А если используется вызов кастомной функции plsql в качестве установки ID, тогда используем IDENTITY, не SEQUENCE, да? Получается при стратегии SEQUENCE хибер не делегирует в бд генерацию айди, а сам ее выполняет основываясь на каком-то внутреннем списке своих сиквенсов, верно?
Anonymous #3322801 Уровень 2 Expert
23 ноября 2023
А почему ничего не сказано про стратегию TABLE?
Виталий Уровень 107 Expert
5 декабря 2023
Потому что она отстой
Anonymous #3322801 Уровень 2 Expert
23 ноября 2023
//это поле будет обработано как будто тут есть @Column(name=”date ”) на самом деле оно будет обработано как @Column(name="createdDate")
Dmitry Parfenov Уровень 108 Expert
12 июля 2023
В шестом гибере есть еще UUID-стратегия.
Igor Уровень 1 Expert
13 декабря 2022
Этих всех лекций не хватало для выполнения проекта по Hibernate
Александр Уровень 111 Expert
19 января 2023
Сначала ты маппишь сущность и разбираешься/изучаешь в какой у тебя тип замапились данные. А потом мы тебе объясним как это работает, в стиле javarush
Дмитрий Уровень 100 Expert
23 января 2024
В каком-то смысле, это может быть правильно. Не то чтобы там прям уж так сложно было с проектом поскольку практически всё, что нужно было для проекта (кроме, пожалуй, автоинкремента у id), было разобрано или подсказано. Да и сам разбор есть. Зато теперь, перечитывая, работает "ага, а я уже так делал" и информация усваивается лучше.