1. Анотація @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;
}

2. Розміщення анотацій

До речі, ти можеш писати анотації @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;
   }
 
}

3. Анотація @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 для твоїх об'єктів, якщо ти про це попросиш.

4. Різні стратегії @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, а не переказ офіційної документації.