Введение: почему hbm2ddl.auto — это и спасение, и головная боль
Каждый, кто хоть раз настраивал Hibernate (или Spring Boot + JPA), сталкивался с загадочной строчкой в application.properties или hibernate.cfg.xml:
spring.jpa.hibernate.ddl-auto=update
# или
hibernate.hbm2ddl.auto=create
На Stack Overflow этот вопрос собрал сотни тысяч просмотров. И не зря: неправильное значение может уничтожить ваши данные, а правильное — сэкономить часы работы. В этой статье мы разберём все возможные значения hibernate.hbm2ddl.auto, покажем реальные примеры кода на Java и заглянем под капот, чтобы понять, как Hibernate на самом деле управляет схемой базы данных.
Что такое hbm2ddl.auto и зачем он нужен?
Hibernate hbm2ddl.auto — это конфигурационный параметр, который управляет автоматическим созданием, обновлением или проверкой схемы базы данных на основе ваших сущностей (Entity). Другими словами, Hibernate смотрит на классы с аннотациями @Entity, @Table, @Column и на лету генерирует SQL-запросы CREATE TABLE, ALTER TABLE и т.д.
Это невероятно удобно на этапе разработки, но может стать причиной катастрофы на продакшене, если не понимать, как каждое значение работает внутри.
Полный список возможных значений hibernate.hbm2ddl.auto
Hibernate поддерживает ровно пять значений (плюс none как отсутствие действия):
validate— только проверка схемыupdate— автоматическое обновлениеcreate— создание заново при стартеcreate-drop— создание при старте и удаление при остановкеnone— ничего не делать (значение по умолчанию)
Давайте разберём каждое значение подробно, с примерами и объяснением, что происходит «под капотом».
1. validate — проверка, но не изменение
Как работает: При старте приложения Hibernate сравнивает ваши Java-сущности с реальной структурой таблиц в базе данных. Если всё совпадает — приложение стартует. Если нет — Hibernate выбрасывает исключение SchemaValidationException.
Пример конфигурации:
// application.properties
spring.jpa.hibernate.ddl-auto=validate
Пример сущности:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "email", nullable = false, length = 255)
private String email;
@Column(name = "age")
private Integer age;
}
Что произойдёт под капотом: Hibernate прочитает метаданные сущности, сформирует внутреннее представление таблицы users с колонками id, email (NOT NULL, длина 255), age. Затем выполнит SQL-запрос к information_schema (или аналогу в вашей БД) и сравнит типы, nullable, длины. Если в БД колонка email имеет тип VARCHAR(100) — будет ошибка.
Когда использовать: Идеально для продакшена, чтобы убедиться, что миграции (Liquibase/Flyway) не нарушили соответствие с кодом.
2. update — автоматическое обновление (с осторожностью!)
Как работает: Hibernate сам добавляет новые таблицы, колонки и ограничения, если их нет в БД. Но он никогда не удаляет колонки и таблицы, даже если вы их убрали из Java-кода.
Пример конфигурации:
// application.properties
spring.jpa.hibernate.ddl-auto=update
Пример изменения сущности: Добавим поле phone:
@Column(name = "phone", length = 20)
private String phone;
Что произойдёт под капотом: Hibernate выполнит ALTER TABLE users ADD COLUMN phone VARCHAR(20). Если таблицы users вообще не существует — создаст её целиком. При удалении поля phone из кода — колонка в БД останется нетронутой.
Важно: update не умеет безопасно менять типы колонок (например, с INT на BIGINT) — это может привести к потере данных. Для сложных изменений используйте миграции.
Когда использовать: Только в разработке и на staging. Никогда — на продакшене.
3. create — пересоздание таблиц при каждом старте
Как работает: При запуске приложения Hibernate удаляет все таблицы, связанные с сущностями, и создаёт их заново. Все данные, которые были в БД, теряются.
Пример конфигурации:
// application.properties
spring.jpa.hibernate.ddl-auto=create
Что произойдёт под капотом: Hibernate выполняет DROP TABLE IF EXISTS users CASCADE, затем CREATE TABLE users (...). Всё это происходит в рамках одной транзакции (если БД поддерживает DDL в транзакциях).
Пример кода для демонстрации:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
// При старте все таблицы будут пересозданы
SpringApplication.run(DemoApplication.class, args);
}
}
Когда использовать: В тестах или при разработке, когда данные не важны. Никогда — на продакшене.
4. create-drop — создание при старте, удаление при остановке
Как работает: Аналогично create, но дополнительно при graceful shutdown приложения Hibernate удаляет все таблицы. Очень удобно для интеграционных тестов.
Пример конфигурации:
// application.properties
spring.jpa.hibernate.ddl-auto=create-drop
Что произойдёт под капотом: При старте — DROP + CREATE. При остановке (когда закрывается SessionFactory) — DROP TABLE IF EXISTS users CASCADE. Обратите внимание: если приложение упадёт с ошибкой, таблицы могут остаться.
Пример в тесте:
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryTest {
// create-drop гарантирует чистую БД для каждого тестового класса
}
Блоги
Рекомендаций по книгам
Читайте также