Enum Mapping with Hibernate 6.3.1

Hi
I have an entity with a mapping for en enum like this.
Database is MySql 8.0.32
Enum is stored in database as a VARCHAR

@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "type", nullable = false)
private AnalysisType type;

Until Hibernate 6.2.x it was OK. But since I have upgraded to Hibernate 6.3.3 (6.4… is the next step) I have and issue like this

encountered in column found varchar but expecting enum

Why it does not work anymore and I have now to set columnDefinition as VARCHAR to fix it ?
@Column(name = "type", nullable = false, columnDefinition = "VARCHAR")

Please try ORM 6.4. Version 6.3 is not supported anymore.

I confirm the same behavior in SpringBoot 3.2.3 (Hibernate 6.4.4.Final, Spring 6.1.4)
When initializing context.

Here is the stack

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [type] in table [balance_analysis]; found [varchar (Types#VARCHAR)], but expecting [enum ('sepa','card','segregated','merchant') (Types#ENUM)]
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateColumnType(AbstractSchemaValidator.java:165)
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:152)
	at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:46)
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:97)
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:75)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:295)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:145)
	at java.base/java.util.HashMap.forEach(HashMap.java:1421)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:142)
	at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37)
	at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:315)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:450)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1507)
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376)
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)
	... 97 common frames omitted
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [type] in table [balance_analysis]; found [varchar (Types#VARCHAR)], but expecting [enum ('sepa','card','segregated','merchant') (Types#ENUM)]
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateColumnType(AbstractSchemaValidator.java:165)
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.validateTable(AbstractSchemaValidator.java:152)
	at org.hibernate.tool.schema.internal.GroupedSchemaValidatorImpl.validateTables(GroupedSchemaValidatorImpl.java:46)
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.performValidation(AbstractSchemaValidator.java:97)
	at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:75)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:295)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:145)
	at java.base/java.util.HashMap.forEach(HashMap.java:1421)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:142)
	at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37)

	at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:315)

	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:450)

	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1507)
============================
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75)
CONDITIONS EVALUATION REPORT
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376)
============================
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409)

	... 97 common frames omitted


Positive matches:
-----------------

    None


Negative matches:
-----------------

    None


Exclusions:
-----------

    None


Unconditional classes:
----------------------

    None

See hibernate-orm/migration-guide.adoc at 6.2 · hibernate/hibernate-orm · GitHub which explains the change in the default mapping.
Even though schema validation will fail, it will work fine. So either you update your schema or you stop using hbm2ddl for schema validation :slight_smile:

Ok I understand that

On MySQL, enums are now stored using the ENUM datatype by default

So I have only 3 solutions

  • Use columnDefinition = "VARCHAR"
  • Migrate my database VARCHAR column to ENUM
  • Create a converter class.

I think I’m going to user a converter because it’s simple and avoid using “columnDefinition” with the column type in database (to avoid linked with database). Use MySQL “ENUM” type is a bit “overkill” in this case and leads to define enum values in database (lead to link java code with database).

Not sure why you think it is an overkill, but do whatever you think is right for your application.

Thank you for your answer and all precisions. I chose the “Converter” according to what I said in my previous answer.

Have same problem.
Could you write more about converter?
Which class (interface) i have to extend to write it?
And how to use it?

Hi
Here is the solution I used

import fr....AnalysisType;
import jakarta.persistence.Column;
import jakarta.persistence.Convert;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.ZonedDateTime;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Entity
@Table(name = "balance_....")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
public class Balance....Entity {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  @NotNull
  @Column(name = "uuid", updatable = false, nullable = false)
  private UUID uuid;

 ....

  @NotNull
  @Convert(converter = AnalysisTypeConverter.class)
  @Column(name = "type", nullable = false)
  private AnalysisType type;

  ....
}

Converter class

import fr.....AnalysisType;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;

@Converter
public class AnalysisTypeConverter implements AttributeConverter<AnalysisType, String> {

  @Override
  public String convertToDatabaseColumn(AnalysisType attribute) {
    return attribute.name();
  }

  @Override
  public AnalysisType convertToEntityAttribute(String name) {
    return AnalysisType.valueOf(name);
  }
}
1 Like

With this solution, did you try to create a spring data repository with a filter using the enum?

When I try to do this I get the following error:
Caused by: org.hibernate.exception.SQLGrammarException: could not execute statement [ERROR: column “status” is of type table_status but expression is of type character varying

I’m not sure to understand. I think you are using in database an ENUM type whereas I store my enum values in VARCHAR. Hibernate mapping depends on your database. What is your database ?
If it is MySQl, ENUM (database type) is the “natural” type mapped by Hibernate
And in this case no need a converter or a column definition. Only something like this.
@Enumerated without anything

@NotNull
@Enumerated
@Column(name = "type", nullable = false)
private AnalysisType type;