javaspringpostgresqlspring-boothibernate

Migrating to hibernate 6 and spring boot 3 try save Enum[]


I migrate my project to hibernate 6.5.3.Final and I can't write value in postgres database

I have field in Entity:

@Nullable
@Column(name = "test_col", columnDefinition = "test_enum_type[]")
@Enumerated(EnumType.STRING)
@JdbcTypeCode(SqlTypes.NAMED_ENUM)

private TestEnum[] testEnum = new TestEnum[0];

Enum:

public enum TestEnum  {
    AAA("fggh"),
    BBB("dffg"),
    CCC("dffg")
}

Database structure:

create type test_enum_type as enum ('AA', 'BB', 'VV');

create table test_table
(
    id                      integer                   default nextval('seq'::regclass) not null
        primary key,
    test_col          test_enum_type[]
);

And method:

objTest.setReceivedData
        .testEnum(new TestEnum[] {TestEnum.AA, TestEnum.BB})
        .build()
);
    

I have error: Cannot read the array length because "values" is null

If I try:

@Nullable
@Column(name = "test_col", columnDefinition = "test_enum_type[]")
@Enumerated(EnumType.STRING)
@JdbcTypeCode(SqlTypes.ARRAY)

private TestEnum[] testEnum = new TestEnum[0];

Error: Caused by: org.postgresql.util.PSQLException: ERROR: column 'test_col' is of type test_enum_type[] and expression is of character varying[] Hint: Rewrite the expression or convert its type.

How it work? How I can save values in database? I found https://discourse.hibernate.org/t/hibernate-6-6-with-array-of-enum/10679/15, but without solved


Solution

  • While Hibernate team is working on the fix and right now there is not a direct way to handle that.

    And based on the console hint: Rewrite the expression or convert its type.

    You can use SQLInsert for persisting and SQLUpdate for update as well to mutate the final query.

    For instance @SqLInsert

    @Entity
    @SQLInsert(sql = "INSERT INTO test_table (test_col, id) VALUES (cast(? AS test_enum_type[]), ?)")
    @Table(name = "test_table")
    public class EntityTest {
    
      @Id
      private Long id;
    
      @Column(name = "test_col")
      @Enumerated(EnumType.STRING)
      @JdbcTypeCode(SqlTypes.ARRAY)
      private TestEnum[] values = new TestEnum[0];
    

    The usage:

    EntityTest entityTest = new EntityTest(new TestEnum[]{TestEnum.setValue("AA")}, 3L);
    testRepository.save(entityTest);
    

    In the same way you will handle updates.

    A good example about the changes before persist you will be able to find out in next blog.