← Назад к вопросам

Как создать сущность в Hibernate?

1.0 Junior🔥 171 комментариев
#ORM и Hibernate

Комментарии (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

Лучшие Практики

  1. Всегда добавляй конструктор без параметров — Hibernate требует
  2. Используй LocalDateTime вместо Date — более современно
  3. Помечай created_at как updatable=false — дата создания не должна меняться
  4. Используй LAZY загрузку для коллекций — избегаешь N+1 проблемы
  5. Думай о каскадах — CascadeType.ALL может быть опасен
  6. Добавляй индексы — через @Index или миграции
  7. Использованный orphanRemoval=true — для правильного удаления
  8. Валидируй с @NotNull, @NotBlank — на уровне сущности

Помни: сущности — это мосты между Java объектами и таблицами БД. Проектируй их с умом!

Как создать сущность в Hibernate? | PrepBro