Hibernate doesn't recognize my enum type declared with @Type annotation

I have the following entity:

@Entity
@Table(name="filter", schema="mailing")
public class FilterItemValue {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Type(
            type = "my.package.generic.enum.GenericEnumUserType",
            parameters = {
                    @Parameter(
                        name  = "enumClass",
                        value = "ua.com.winforce.casino.email.db.entity.FilterItem"),
                    @Parameter(
                        name  = "identifierMethod",
                        value = "getValue"),
                    @Parameter(
                        name  = "valueOfMethod",
                        value = "getByValue")
                    }
        )
    @Column(name = "filter_item_id")
    private FilterItem filterItemId;

    //Other fields and properties
}

      

Where GenericEnumUserType:

public class GenericEnumUserType implements UserType, ParameterizedType {

    private static final String DEFAULT_IDENTIFIER_METHOD_NAME = "name";
    private static final String DEFAULT_VALUE_OF_METHOD_NAME = "valueOf";

    private Class<? extends Enum> enumClass;
    private Class<?> identifierType;
    private Method identifierMethod;
    private Method valueOfMethod;
    private NullableType type;
    private int[] sqlTypes;

    public void setParameterValues(Properties parameters) {
        String enumClassName = parameters.getProperty("enumClass");
        try {
            enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
        } catch (ClassNotFoundException cfne) {
            throw new HibernateException("Enum class not found", cfne);
        }

        String identifierMethodName = parameters.getProperty("identifierMethod", DEFAULT_IDENTIFIER_METHOD_NAME);

        try {
            identifierMethod = enumClass.getMethod(identifierMethodName, new Class[0]);
            identifierType = identifierMethod.getReturnType();
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain identifier method", e);
        }

        type = (NullableType) TypeFactory.basic(identifierType.getName());

        if (type == null)
            throw new HibernateException("Unsupported identifier type " + identifierType.getName());

        sqlTypes = new int[] { type.sqlType() };

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

        try {
            valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[] { identifierType });
        } catch (Exception e) {
            throw new HibernateException("Failed to obtain valueOf method", e);
        }
    }

    public Class returnedClass() {
        return enumClass;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        Object identifier = type.get(rs, names[0]);
        if (identifier == null) {
            return null;
        }

        try {
            return valueOfMethod.invoke(enumClass, new Object[] { identifier });
        } catch (Exception e) {
            throw new HibernateException("Exception while invoking valueOf method '" + valueOfMethod.getName() + "' of " +
                    "enumeration class '" + enumClass + "'", e);
        }
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        try {
            if (value == null) {
                st.setNull(index, type.sqlType());
            } else {
                Object identifier = identifierMethod.invoke(value, new Object[0]);
                type.set(st, identifier, index);
            }
        } catch (Exception e) {
            throw new HibernateException("Exception while invoking identifierMethod '" + identifierMethod.getName() + "' of " +
                    "enumeration class '" + enumClass + "'", e);
        }
    }

    public int[] sqlTypes() {
        return sqlTypes;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object value) throws HibernateException {
        return value;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return x == y;
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public boolean isMutable() {
        return false;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

      

and the enumeration itself:

public enum FilterItem implements StringRepresentable{

    AMOUNT(1) {
            @Override
            public List<RuleItem> getItemRules() {
                List<RuleItem> result = new ArrayList<RuleItem>();
                result.add(RuleItem.EQUAL);
                return result;
            }

            @Override
            public FilterItemType getFilterItemType() {
                return FilterItemType.FIELD;
            }

            @Override
            public String getStringRepresentation() {
                return getFilterItemStringRepresentation("dynamicFilterItemName.amount");
            }

            @Override
            public MapperType getMapperType() {
                return null;
            }

            @Override
            public RestrictorType getRestrictorType() {
                return RestrictorType.RANDOM_AMOUNT;
            }

            @Override
            public JunctionBuilderParams getJunctionBuilderParams() {
                return null;
            }
        },

        //Other enums

    public static FilterItem getByValue(int val) {
        FilterItem[] values = FilterItem.values();
        for (FilterItem value : values) {
            if (val == value.getValue()) {
                return value;
            }
        }
        throw new IllegalArgumentException("Illegal value: " + val);
    }

    public abstract String getStringRepresentation();

    public abstract List<RuleItem> getItemRules();

    public abstract FilterItemType getFilterItemType();

    public abstract MapperType getMapperType();

    public abstract RestrictorType getRestrictorType();

    public abstract JunctionBuilderParams getJunctionBuilderParams();
}

      

So when I debug the application, the method

public static Type heuristicType(String typeName, Properties parameters)
            throws MappingException

      

at org.hibernate.type.TypeFactory

first executes this instruction Type type = TypeFactory.basic( typeName );

, where typeName = "GenericEnumUserType"

. So it TypeFactory.basic(typename)

returns null and I end up with an exception:

org.hibernate.MappingException: Could not determine type for: my.package.generic.enum.GenericEnumUserType, for columns: [org.hibernate.mapping.Column(filter_item_id)]
    org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:266)
    org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)

      

How to fix it, what's wrong?

Perhaps this was caused by abstract methods that I defined in the FilterItem

enum?

+3


source to share





All Articles