Search code examples
javaenumshashmaphibernate-annotations

How to annotate an EnumMap with an Enum as a value in hibernate?


I'm using Hibernate annotations in a class containing a map of properties, which are basically <name, value> pairs. The property names are defined in a PROPERTY enum, and each property has a set of permissible values, also defined as an enum. Since each property has its own enum defined for its values, the property map is defined as

Map<PROPERTY, Enum> properties = new EnumMap<PROPERTY, Enum> (PROPERTY.class);

I am having trouble mapping the Enum value. This definition:

@ElementCollection
@MapKeyEnumerated(EnumType.STRING)
@MapKeyColumn(name="name")
@Column(name="value")
@Enumerated(EnumType.STRING)
Map<PROPERTY, Enum> properties = new EnumMap<PROPERTY, Enum> (PROPERTY.class);

generates the following DDL:

create table EnumMapTest (
    id bigint not null auto_increment,
    primary key (id)
) ENGINE=InnoDB;

create table EnumMapTest_properties (
    EnumMapTest_id bigint not null,
    value tinyblob,
    name varchar(255) not null,
    primary key (EnumMapTest_id, name)
) ENGINE=InnoDB;

As you can see, the Enum class is mapped as a tinyblob, which is totally unreadable in the database.

If I define the map with a concrete enum

enum VALUE {ONE, TWO, THREE};

@ElementCollection
@MapKeyEnumerated(EnumType.STRING)
@MapKeyColumn(name="name")
@Column(name="value")
@Enumerated(EnumType.STRING)
Map<PROPERTY, VALUE> properties = new EnumMap<PROPERTY, VALUE> (PROPERTY.class);

the mapping is fine:

create table EnumMapTest_properties (
    EnumMapTest_id bigint not null,
    value varchar(255),
    name varchar(255) not null,
    primary key (EnumMapTest_id, name)
) ENGINE=InnoDB;

So the issue is the mapping of the Enum class itself.

Is there a way to do map an Enum to something readable (preferably a string) without creating a custom type?

I hope the fact that we are still at Hibernate 3.6.10 won't be held against us.

TIA for any assistance


Solution

  • If you don't specify any type, hibernate saves it using serialization. That's why it generates a tinyblob.

    In your case, I would recommend that you make a Map of strings (Map<PROPERTY, String>) since you just use Enum values. You have to convert the enums to string by hand (combination of enum-class name and enum-name) but it's readable.