Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Как создать сущность в Hibernate?
Hibernate сущность (Entity) — это Java класс, который маппируется на таблицу БД. Рассмотрим различные способы создания и конфигурации.
1. Базовая Сущность
import jakarta.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "users")
public class User {
@Id // Первичный ключ
@GeneratedValue(strategy = GenerationType.IDENTITY) // Auto-increment
private Long id;
@Column(name = "email", nullable = false, unique = true, length = 255)
private String email;
@Column(name = "name", nullable = false, length = 100)
private String name;
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
// Конструктор без параметров (требуется для Hibernate)
public User() {}
// Конструктор с параметрами
public User(String email, String name) {
this.email = email;
this.name = name;
this.createdAt = LocalDateTime.now();
}
// Геттеры и сеттеры
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
2. Стратегии Генерации ID
IDENTITY (Auto-increment)
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; // БД генерирует ID автоматически
}
Лучше всего для: MySQL, H2, Derby
SEQUENCE (Последовательность БД)
@Entity
@Table(name = "users")
@SequenceGenerator(
name = "user_seq_generator",
sequenceName = "user_sequence",
allocationSize = 1
)
public class User {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "user_seq_generator"
)
private Long id; // Используется БД SEQUENCE
}
Лучше всего для: PostgreSQL, Oracle
TABLE (Таблица для ID)
@Entity
@Table(name = "users")
@TableGenerator(
name = "id_generator",
table = "id_sequences",
pkColumnName = "sequence_name",
valueColumnName = "next_value",
pkColumnValue = "user_id"
)
public class User {
@Id
@GeneratedValue(
strategy = GenerationType.TABLE,
generator = "id_generator"
)
private Long id; // ID берется из таблицы
}
UUID (Универсальный идентификатор)
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.UUID) // Hibernate 6+
private String id;
// или вручную:
@Id
private UUID id = UUID.randomUUID();
}
3. Типы Полей и Аннотации
Простые типы
@Entity
public class Product {
@Id
private Long id;
@Column(name = "name", nullable = false, length = 255)
private String name; // VARCHAR(255)
@Column(name = "price", precision = 10, scale = 2)
private BigDecimal price; // DECIMAL(10,2)
@Column(name = "quantity")
private Integer quantity; // INTEGER
@Column(name = "available")
private Boolean available; // BOOLEAN
@Column(name = "rating")
private Double rating; // DOUBLE
}
Дата и Время
@Entity
public class Event {
@Id
private Long id;
@Column(name = "created_at", nullable = false, updatable = false)
private LocalDateTime createdAt; // TIMESTAMP
@Column(name = "updated_at")
private LocalDateTime updatedAt; // TIMESTAMP
@Column(name = "event_date")
private LocalDate eventDate; // DATE
@Column(name = "event_time")
private LocalTime eventTime; // TIME
@PrePersist // Вызывается перед INSERT
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}
@PreUpdate // Вызывается перед UPDATE
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
Enum
public enum UserRole {
ADMIN, USER, GUEST
}
@Entity
public class User {
@Id
private Long id;
@Enumerated(EnumType.STRING) // Хранится как 'ADMIN', 'USER'
@Column(name = "role")
private UserRole role; // VARCHAR(50) в БД
// или
@Enumerated(EnumType.ORDINAL) // Хранится как 0, 1, 2
@Column(name = "status")
private Status status; // INTEGER в БД
}
JSON (PostgreSQL)
@Entity
public class Document {
@Id
private Long id;
@Column(columnDefinition = "jsonb")
private Map<String, Object> metadata; // JSON column
}
4. Отношения Между Сущностями
One-to-Many (Один ко многим)
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Post> posts = new ArrayList<>(); // У одного User много Posts
}
@Entity
@Table(name = "posts")
public class Post {
@Id
private Long id;
private String title;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
private User user; // Post принадлежит одному User
}
Many-to-One (Много к одному)
См. пример выше (обратная сторона One-to-Many).
Many-to-Many (Много ко многим)
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String name;
@ManyToMany(cascade = CascadeType.PERSIST)
@JoinTable(
name = "user_roles", // Таблица-связка
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>(); // Много roles у одного user
}
@Entity
@Table(name = "roles")
public class Role {
@Id
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<>(); // Много users с этой role
}
One-to-One (Один к одному)
@Entity
@Table(name = "users")
public class User {
@Id
private Long id;
private String name;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "profile_id", unique = true)
private UserProfile profile; // У каждого User один Profile
}
@Entity
@Table(name = "user_profiles")
public class UserProfile {
@Id
private Long id;
private String bio;
@OneToOne(mappedBy = "profile")
private User user; // Обратная сторона
}
5. Наследование в Сущностях
Single Table (одна таблица)
@Entity
@Table(name = "vehicles")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type")
public abstract class Vehicle {
@Id
private Long id;
private String name;
}
@Entity
@DiscriminatorValue("car")
public class Car extends Vehicle {
private int doors;
}
@Entity
@DiscriminatorValue("bike")
public class Bike extends Vehicle {
private boolean hasSidecar;
}
// Одна таблица vehicles с колонкой type
Joined (отдельные таблицы)
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Vehicle {
@Id
private Long id;
private String name;
}
@Entity
public class Car extends Vehicle {
private int doors;
}
// Две таблицы: vehicle и car, связанные по ID
6. Валидация и Ограничения
import jakarta.validation.constraints.*;
@Entity
public class User {
@Id
private Long id;
@NotBlank(message = "Email не может быть пустым")
@Email(message = "Email должен быть корректным")
@Column(unique = true, nullable = false)
private String email;
@NotBlank
@Size(min = 3, max = 100, message = "Имя должно быть от 3 до 100 символов")
private String name;
@Positive(message = "Возраст должен быть положительным числом")
@Column(name = "age")
private Integer age;
@Min(0)
@Max(5)
private Integer rating;
}
7. Полный Пример Сущности
@Entity
@Table(
name = "users",
indexes = {
@Index(name = "idx_email", columnList = "email", unique = true),
@Index(name = "idx_created_at", columnList = "created_at")
}
)
@EntityListeners(AuditListener.class) // Слушатель для аудита
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Email
@Column(unique = true, nullable = false, length = 255)
private String email;
@NotBlank
@Size(min = 3, max = 100)
@Column(nullable = false, length = 100)
private String name;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private UserRole role = UserRole.USER;
@CreationTimestamp // Hibernate автоматически устанавливает
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp // Hibernate автоматически обновляет
@Column(nullable = false)
private LocalDateTime updatedAt;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Post> posts = new ArrayList<>();
@OneToOne(cascade = CascadeType.ALL)
private UserProfile profile;
public User() {}
public User(String email, String name) {
this.email = email;
this.name = name;
}
// Геттеры и сеттеры
public Long getId() { return id; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<Post> getPosts() { return posts; }
public void addPost(Post post) {
posts.add(post);
post.setUser(this);
}
}
8. Конфигурация Hibernate
JPA persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="https://jakarta.ee/xml/ns/persistence">
<persistence-unit name="default">
<class>com.example.User</class>
<class>com.example.Post</class>
<properties>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost/mydb"/>
<property name="jakarta.persistence.jdbc.user" value="root"/>
<property name="jakarta.persistence.jdbc.password" value="password"/>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL8Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
Spring Boot application.yml
spring:
datasource:
url: jdbc:mysql://localhost/mydb
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: validate # НЕ create/update в production!
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
use_sql_comments: true
show_sql: true
Лучшие Практики
- Всегда добавляй конструктор без параметров — Hibernate требует
- Используй LocalDateTime вместо Date — более современно
- Помечай created_at как updatable=false — дата создания не должна меняться
- Используй LAZY загрузку для коллекций — избегаешь N+1 проблемы
- Думай о каскадах — CascadeType.ALL может быть опасен
- Добавляй индексы — через @Index или миграции
- Использованный orphanRemoval=true — для правильного удаления
- Валидируй с @NotNull, @NotBlank — на уровне сущности
Помни: сущности — это мосты между Java объектами и таблицами БД. Проектируй их с умом!