Reputation: 311
Using a legacy db schema with newest Hibernate 6.3.1.Final with Spring Boot 3.1.4 has had quite a few code migration work needed for JPA models. Most of my issues currently are with Enum types. I've had issue with Enums in the mysql database that were stored as int(11) producing "expecting #TINYINT" errors, which I could only solve by changing the column type in the db (something that would break legacy code). I tried these changes to the annotation to no avail, and I couldn't find any other solution in blogs. Note: I did not have these validation issues with Hibernate 6.0.1.Final:
@Column(name="status", columnDefinition = "INTEGER") or @Column(name="status", columnDefinition = "int2")
Another issue was with "@Enumerated(EnumType.STRING)", which doesn't seem to work at all. Documentation from https://docs.jboss.org/hibernate/orm/6.3/introduction/html_single/Hibernate_Introduction.html#enums isn't complete or no longer accurate. I have an enum in a legacy database stored as "varchar(255)", with the following JPA definition:
@Column(name = "status", nullable = false)
@Enumerated(EnumType.STRING)
@Basic(optional=false)
private ActiveOrInactive status;
And I get the following error on validation:
found [varchar (Types#VARCHAR)], but expecting [enum ('active','inactive') (Types#ENUM)]
Again, I did not get this issue with Hibernate 6.0.1.Final.
What changes should I make to my annotation for Enums stored as int(11) or varchar(255) in Mysql db?
import java.util.HashMap;
import java.util.Map;
public enum ActiveOrInactive {
Active, Inactive;
static final Map<String, ActiveOrInactive> _activeOrInactive = new HashMap<String, ActiveOrInactive>();
static {
for (ActiveOrInactive activeOrInactive : ActiveOrInactive.values()) {
_activeOrInactive.put(activeOrInactive.toString(), activeOrInactive);
}
}
public static Map<String, ActiveOrInactive> getPublishedStateTypes() {
return _activeOrInactive;
}
}
Upvotes: 3
Views: 3314
Reputation: 2422
I believe you should use a Custom Converter for this.
I am giving an example for datatype
varchar
in your database i.e., @Enumerated(EnumType.STRING)
, if it is for int
, changes in your custom converter class can be made accordingly.
@Converter
public class ActiveOrInactiveConverter implements Serializable, AttributeConverter<ActiveOrInactive, String> {
@Override
public String convertToDatabaseColumn(ActiveOrInactive attribute) {
if (attribute == null) {
return null;
}
return attribute.name();
}
@Override
public ActiveOrInactive convertToEntityAttribute(String dbData) {
if (dbData == null) {
return null;
}
return ActiveOrInactive.valueOf(dbData);
}
}
And
You should replace your
@Enumerated(EnumType.STRING)
with
@Convert(converter = ActiveOrInactiveConverter.class)
It should look like:
@Column(name = "status", nullable = false)
@Convert(converter = ActiveOrInactiveConverter.class)
@Basic(optional=false)
private ActiveOrInactive status;
Here is a reference
Upvotes: 0
Reputation: 159
According to https://docs.jboss.org/hibernate/orm/6.3/introduction/html_single/Hibernate_Introduction.html
@Enumerated(EnumType.STRING)
is mapped to varchar, except for Mysql (and maybe MariaDB) where it is mapped to an ENUM column type.
If you change:
@Column(name = "status", nullable = false)
to:
@Column(name = "status", nullable = false, columnDefinition = "varchar")
you can make hibernate understand that it's a varchar column.
Upvotes: 6