Hibernate 6 cannot read VARCHAR column as INT
Description
Attachments
- 06 Sep 2024, 07:48 AM
Activity
Andrea Boriero September 6, 2024 at 8:41 AMEdited
Thanks @Lars Benedetto for the feedback,
it seems that a possible workaround can be to use @JdbcTypeCode(SqlTypes.INTEGER)
or a better solution can be to change the enum
definition adding the @EnumeratedValue
annotation in this way
public enum MyEnum {
A(0),
B(1);
@EnumeratedValue
final int intValue;
MyEnum(int intValue) {
this.intValue = intValue;
}
}
can you give a try and let me know if it works?
Thanks.
Lars Benedetto September 6, 2024 at 7:30 AMEdited
Ah, nevermind, it passed tests locally but when deployed to run against existing data, it fails.
Caused by: java.lang.IllegalArgumentException: No enum constant dk.tgtg.service.domain.ExpirationStrategy.3
at java.base/java.lang.Enum.valueOf(Enum.java:293)
29 lines skipped for [org.hibernate]
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:223)
It interprets the String “3” from the database as the name of the enum instead of as the ordinal.
The enum looks like this:
public enum ExpirationStrategy {
/* 0 */
SESSION_CONSUMER,
/* 1 */
SESSION_STORE_OWNER,
/* 2 */
SESSION_ADMIN,
/* 3 */
REFRESH_TOKEN,
And the issue is that the ordinal value 3
is stored in the DB as a String, which confuses Hibernate.
Your suggested change causes Hibernate to write the enum name to the database instead:
Here is a screenshot of my database. My code normally writes numbers but with your fix it writes strings.
Lars Benedetto September 5, 2024 at 3:39 PM
Interesting. I just tried it out on my code and it does indeed work.
This is strange because in the original thread that same annotation was suggested and it didn’t work:
Andrea Boriero September 5, 2024 at 1:23 PM
Hi @Lars Benedetto,
I have just tried with Hibernate 6.0.0.Final adding the @JdbcTypeCode(SqlTypes.VARCHAR)
and the test passes.
@Enumerated(value = EnumType.ORDINAL)
@Column(columnDefinition = "VARCHAR(255) NOT NULL")
@JdbcTypeCode(SqlTypes.VARCHAR)
MyEnum myEnum;
Can you please double check?
Thanks
https://discourse.hibernate.org/t/hibernate-6-cannot-persist-enum-as-ordinal-in-varchar-column/7775/17
As discussed in this thread, in Hibernate 6 if a column is VARCHAR, but actually contains integers meant to be mapped with
@Enumerated(value = EnumType.ORDINAL)
then you’ll get an exception caused by it using the char value of the int from the db as the ordinal index. So a 0 in the db becomes a 48.java.lang.ArrayIndexOutOfBoundsException: Index 48 out of bounds for length 2 at org.hibernate.type.descriptor.java.EnumJavaType.fromInteger(EnumJavaType.java:194) at org.hibernate.type.descriptor.java.EnumJavaType.fromOrdinal(EnumJavaType.java:211) at org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter.toDomainValue(OrdinalEnumValueConverter.java:40) at org.hibernate.type.descriptor.converter.internal.OrdinalEnumValueConverter.toDomainValue(OrdinalEnumValueConverter.java:23)
In Hibernate 5, this worked without issue.
https://github.com/lbenedetto/HHH-17017-Issue-Reproducer