Ответ
Для маппинга класса на таблицу БД с помощью JPA/Hibernate класс должен быть сущностью (Entity). Основные шаги и свойства:
- Пометить класс аннотацией
@Entity. - Определить первичный ключ с помощью
@Id. Часто используется@GeneratedValueдля автоматической генерации ID. - Сопоставить класс с таблицей (опционально, но рекомендуется) с помощью
@Table(name = "table_name"). - Сопоставить поля со столбцами с помощью
@Column. Без этой аннотации поле всё равно будет маппиться на столбец с тем же именем. - Соблюсти требования JPA к Entity (пустой конструктор, не-final класс и методы).
Полный пример маппинга:
@Entity // 1. Объявляем сущность
@Table(name = "employees") // 3. Указываем имя таблицы
public class Employee {
@Id // 2. Первичный ключ
@GeneratedValue(strategy = GenerationType.IDENTITY) // Автоинкремент в БД
private Long id;
@Column(name = "full_name", length = 200, nullable = false) // 4. Маппинг поля
private String name;
@Column(unique = true) // Ограничение UNIQUE
private String email;
@Transient // Поле НЕ будет сохранено в БД
private String temporaryCode;
// 5. Обязательный конструктор
public Employee() {}
// Конструктор для удобства
public Employee(String name, String email) {
this.name = name;
this.email = email;
}
// Геттеры и сеттеры...
}
Ключевые аннотации для связей между таблицами:
@OneToMany,@ManyToOne,@OneToOne,@ManyToMany— для отображения связей.@JoinColumn— для указания столбца внешнего ключа.
Почему @Column не всегда обязателен?
Hibernate по умолчанию маппит поле на столбец с тем же именем. Однако @Column необходим для задания дополнительных свойств: nullable, unique, length (для строк), precision/scale (для чисел).
Ответ 18+ 🔞
Давай разберём эту всю хрень с маппингом, а то я вижу, у некоторых глаза уже стеклянные, как у пойманной Муму перед утоплением.
Вот смотри, чтобы твой обычный, ни в чём не повинный Java-класс стал полноценной сущностью в базе данных, его надо правильно обрядить. Как наряжают покойника, только веселее.
Первое и главное — ты должен крикнуть на весь мир, что этот класс теперь сущность. Вешаешь на него аннотацию @Entity. Без этого — нихуя не работает, Hibernate на тебя даже смотреть не будет.
@Entity // 1. Всё, чувак, ты теперь не просто POJO, ты — Entity. Поздравляю, блядь.
Дальше — каждому уважающему себя объекту в базе нужен паспорт, уникальный идентификатор. Это @Id. А чтобы не париться с придумыванием чисел, вешаем @GeneratedValue. Стратегия IDENTITY — это типа "база, роди мне новый айдишник, когда я вставляю запись".
@Id // 2. Это твой главный ключ, первичный, блядь. Без него — пиздец.
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Теперь про таблицы. По умолчанию Hibernate создаст таблицу с именем класса. Но если ты не конченый мазохист и у тебя в базе таблицы называются не MySuperPuperEntity, а, допустим, users, то надо явно указать. Для этого @Table(name = "название_таблицы").
@Table(name = "employees") // 3. Чтоб не в `employee`, а именно в `employees`. Чисто для приличия.
Поля и колонки. Тут, в принципе, можно нихуя не делать. Hibernate сам догадается, что поле email надо положить в колонку email. Но если ты хочешь быть хитрожопым и задать ограничения (типа NOT NULL, длину строки или UNIQUE), то без @Column — никуда.
@Column(name = "full_name", length = 200, nullable = false) // 4. Имя в колонке `full_name`, не больше 200 символов и НЕ NULL, ёпта!
private String name;
@Column(unique = true) // Ограничение UNIQUE. Два одинаковых email'а — и будет тебе конфликт, пиздец.
private String email;
А бывают поля-призраки. Они есть в Java-объекте, но в базу их класть не надо. Например, какая-нибудь временная хуйня для вычислений. Для этого — @Transient. Словно его и нет.
@Transient // Поле НЕ будет сохранено в БД. Как сон, как утренний туман.
private String temporaryCode;
И да, не забудь про священный ритуал JPA — пустой конструктор. Без него Hibernate обосрётся с ошибкой, когда будет пытаться создать объект через рефлексию. Класс и методы не должны быть final. В общем, играй по правилам, пидрила.
// 5. Обязательный пустой конструктор. Даже если он тебе не нужен. Сделал и забыл.
public Employee() {}
А теперь смотри, как это всё вместе выглядит, этот шедевр маппинга:
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "full_name", length = 200, nullable = false)
private String name;
@Column(unique = true)
private String email;
@Transient
private String temporaryCode;
public Employee() {}
public Employee(String name, String email) {
this.name = name;
this.email = email;
}
// Геттеры и сеттеры... (без них тоже, в принципе, можно, но некрасиво)
}
Ну и на последок, про связи. Это когда одни сущности ссылаются на другие. Тут тебе в помощь целый арсенал: @OneToMany, @ManyToOne, @OneToOne, @ManyToMany. А чтобы указать, в какой колонке лежит внешний ключ — @JoinColumn. Но это уже, как говорится, совсем другая история, ебать её в сраку. Для первого раза и этого овердохуища хватит.