Search code examples
javahibernatehibernate-5.x

Upgrading to Hibernate 5: how to get type mapping now that TypeResolver is deprecated


I'm working with an older codebase which has a LOT of entities using enums like this (currently using Hibernate 3), with a "generifying" GenericEnumUserType class:

@Entity
@Table(name = "dog")
@TypeDefs({
    @TypeDef(name = "DogEnumType",
    typeClass = com.GenericEnumUserType.class,
    parameters = {
            @Parameter(name = "enumClass", value = "com.DogStateEnum"),
            @Parameter(name = "identifierMethod", value = "value"),
            // could return different type depending on enum
            @Parameter(name = "valueOfMethod", value = "fromValue")
    }
)
})
public class Dog implements Serializable {

...

    @Type(type = "DogEnumType")
    public DogStateEnum getDogState() {
        return this.dogState;
    }

...

GenericEnumUserType (idea being valueOf method's java return type is mapped to the appropriate sql type):

public class GenericEnumUserType implements UserType, ParameterizedType {

...
    private Method valueOfMethod;
    private int[] sqlTypes;
...

    public void setParameterValues(Properties parameters) {
        // Something along the lines of:
        String enumClassName = parameters.getProperty("enumClass");

        enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
      
        String identifierMethodName = parameters.getProperty("identifierMethod");

        identifierMethod = enumClass.getMethod(identifierMethodName);
        identifierType = identifierMethod.getReturnType();

        // TypeResolver is now deprecated!!
        type = (AbstractSingleColumnStandardBasicType<? extends Object>) new TypeResolver().heuristicType(identifierType.getName(), parameters);

        sqlTypes = new int[] { ((AbstractSingleColumnStandardBasicType<?>) type).sqlType() };

        String valueOfMethodName = parameters.getProperty("valueOfMethod");

        valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[] { identifierType });
    }
...

Now that TypeResolver has been deprecated with no replacement, what is the appropriate way to look up the mapping from java type to sql type? And if this is impossible, what is the recommended approach to migrate this type of code?

I can see Hibernate now has org.hibernate.type.EnumType but the implementation assumes ordinal/string which is likely fine but is a much bigger refactor (there is also more than 1 generic enum).


Solution

  • This is most likely unnecessary needed now that Hibernate maps enums out of the box. Unless something unusual was implemented here these enums are either saved with their String representation or with their ordinal.

    By default Hibernate will assume that you're mapping the ordinal. In case GenericEnumUserType was doing that as well you can simply remove the @Type(type = "DogEnumType") annotation. Note that in that case you need to be careful when adding/removing values in enums.

    Otherwise you need to tell Hibernate that you want the String value stored in the database using the @Enumerated annotation:

    @Enumerated(EnumType.STRING)
    public DogStateEnum getDogState() {
        return this.dogState;
    }
    

    And you can drop the @TypeDefs annotation.

    Note that there's also the @MapKeyEnumerated annotation when enums are used as map keys.