Со следующими компонентами базы данных postgresql и удалением аннотаций @Type и @Typedef в Spring Boot 3 (Hibernate 6), как мне сохранить перечисление как строку в базе данных, когда база данных также использует тип Enum для этого столбца.
Пример базы данных PG:
CREATE TYPE TEST_TYPE AS ENUM ('TESTA','TESTB');
CREATE TABLE test_table (
id INT NOT NULL PRIMARY KEY,
type TEST_TYPE NOT NULL
);
со следующей сущностью
@Entity
@Table(name = "test_table")
public class TestTableEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TestType tenantId;
}
Это не удается с ошибкой, потому что он пытается сохранить его как строку вместо типа перечисления.
Все остальные ресурсы ссылаются на библиотеку hypersistence-utils, hibernate-types-62. Однако мне не нужно зависеть от внешней библиотеки утилит.
Другие решения неуклюжи и требуют реализации новой иерархии только для перечислений.
Какое более простое решение для PostgreSQL?
Вы можете использовать ColumnTransformers для изменения SQL, сгенерированного Hibernate.
Это рабочий пример объекта:
@Entity
@Table(name = "test_table")
public class TestTableEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Enumerated(EnumType.STRING)
@Column(name = "type")
@ColumnTransformer(write = "?::TEST_TYPE")
private TestType tenantId;
}
Если это часть другой схемы, вам может потребоваться сделать
@ColumnTransformer(write = "?::other_table.TEST_TYPE")
Если вы проверите сгенерированный SQL, он будет использовать аннотацию @Enumerated для передачи TestType в виде строки. Затем ColumnTransformer добавит приведение для записи, позволяя запросу на вставку/обновление БД предоставить правильный тип параметра для предполагаемого столбца.
На обратном пути, поскольку @Enumerated настроен на использование String, Hibernate определит на основе сохраненной String, какой Enum выбрать и вернуть.
Это простой однострочный код, который не требует написания пользовательского типа UserType или использования библиотеки только для поддержки Enum.
Начиная с Hibernate 6.2, Hibernate по умолчанию использует типы enum в MySQL.
Например, этот код:
public enum TestType {
TESTA, TESTB
}
@Entity
@Table(name = "test_table")
public class TestTableEntity
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Enumerated(EnumType.STRING)
@Column(name = "type")
private TestType tenantId;
}
Создает следующий DDL:
create table test_table (
id integer not null auto_increment,
type enum ('TESTA','TESTB'),
primary key (id)
) engine=InnoDB
Так что тут ничего делать не надо, просто обновитесь до 6.2.
Однако это еще не реализовано для PostgreSQL, который, я думаю, вы используете (вы не указали). Проблема, которая предлагает добавить это:
https://hibernate.atlassian.net/browse/HHH-16125
Да! Спасибо, что назвали это, это будет хорошим дополнением для будущих читателей. Я добавлю уточнение конкретно для PostgreSQL.