Spring Boot 如何在Hibernate 6 Sping Boot 3中将枚举持久化为字符串而不使用hibernate-types-62

bpsygsoo  于 2023-04-20  发布在  Spring
关注(0)|答案(2)|浏览(147)

使用以下数据库组件并在Sping Boot 3(Hibernate 6)中删除@Type和@Typedef注解,当数据库也为该列使用Enum类型时,如何将枚举作为String持久化在数据库中。
数据库示例:

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。但是,我不需要依赖于外部utils库。
其他的解决方案很笨拙,需要为枚举实现一个新的层次结构。
更简单的解决方案是什么?

6jjcrrmo

6jjcrrmo1#

您可以使用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;
}

如果它是另一个模式的一部分,您可能需要

@ColumnTransformer(write = "?::other_table.TEST_TYPE")

如果您检查生成的SQL,这将使用@Enumerated注解将TestType作为字符串传递。然后ColumnTransformer将添加用于写入的强制转换,允许DB的插入/更新查询为预期的列提供正确的参数类型。
在返回的过程中,由于我们已经将@Enumerated配置为使用String,Hibernate将根据存储的String计算出选择并返回哪个Enum。
这是一个简单的一行程序,不需要编写自定义的UserType或引入库来支持Enum。

gojuced7

gojuced72#

从Hibernate 6.2开始,Hibernate默认在MySQL上使用enum类型。
https://docs.jboss.org/hibernate/orm/6.2/migration-guide/migration-guide.html#ddl-implicit-datatype-enum
例如,下面的代码:

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

相关问题