如何在 Hibernate 6 Spring Boot 3 中将枚举保留为字符串,而不在 PostgreSQL 中使用 hibernate-types-62

Ste*_*nPG 2 enums spring hibernate jpa spring-boot

通过以下 postgresql 数据库组件以及在 Spring Boot 3 (Hibernate 6) 中删除 @Type 和 @Typedef 注释,当数据库也对该列使用 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
);
Run Code Online (Sandbox Code Playgroud)

与以下实体

@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;
}
Run Code Online (Sandbox Code Playgroud)

此操作失败并出现错误,因为它尝试将其保留为字符串而不是枚举类型。

所有其他资源均使用 hypersistence-utils 库 hibernate-types-62 进行引用。但是,我不需要依赖外部 utils 库。

其他解决方案很笨重,需要仅为枚举实现新的层次结构。

PostgreSQL 更简单的解决方案是什么?

Ste*_*nPG 6

您可以使用 ColumnTransformers 来更改 Hibernate 生成的 SQL。

这是该实体的一个工作示例:

@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;
}
Run Code Online (Sandbox Code Playgroud)

如果它是不同架构的一部分,您可能需要这样做

@ColumnTransformer(write = "?::other_table.TEST_TYPE")
Run Code Online (Sandbox Code Playgroud)

如果您检查生成的 SQL,这将使用 @Enumerated 注释将 TestType 作为字符串传递。然后,ColumnTransformer 将添加用于写入的转换,允许数据库的插入/更新查询为预期列提供正确的参数类型。

在返回时,由于我们已将 @Enumerated 配置为使用 String,Hibernate 将根据存储的 String 计算出要选择并返回哪个 Enum。

这是一个简单的单行代码,不需要编写自定义 UserType 或引入库来支持枚举。