82

It is often useful to have a field in a DAO whose value comes from a Java enumeration. A typical example is a login DAO where you usually have a field that characterises the user as "NORMAL" or "ADMIN". In Hibernate, I would use the following 2 objects to represent this relationship in a (semi-)typesafe way:

class User {
    String username;
    String passwd;
    UserType type;
}

class UserType {
    private enum Type {ADMIN, NORMAL};
    private String type;

    //Setters/Getters for Hibernate
    public void setType(String type);
    public String getType();

    //Setters/Getters for user
    public void setUserType(UserType.Type t);
    public UserType.Type getUserType();

    public static UserType fromType(UserType.Type t);
}

This works, but I find the UserType class ungly and requiring too much bureaucracy just to store a couple of values. Ideally, Hibernate should support enum fields directly and would create an extra table to store the enumeration values.

My question is: Is there any way to directly map an enumeration class in Hibernate? If not, is my pattern for representing enumerations good enough or am I missing something? What other patterns do people use?

Anthony
  • 12,407
  • 12
  • 64
  • 88
Georgios Gousios
  • 2,405
  • 1
  • 24
  • 34

2 Answers2

111

using hibernate or JPA annotations:

class User {
   @Enumerated(EnumType.STRING)
   UserType type
}

UserType is just a standard java 5 enum.

I can't imagine this is just limited to just annotations but I don't actually know how to do this with hbm files. It may be very version dependant, I'm guessing but I'm pretty sure that hibernate 3.2+ is required.

edit: it is possible in a hbm, but is a little messy, have a look at this forum thread

Gareth Davis
  • 27,701
  • 12
  • 73
  • 106
  • 3
    Could @Enumerated(EnumType.ORDINAL) which map to int more efficient? – Lee Chee Kiam Jan 11 '11 at 03:20
  • 4
    problably is more efficient, but I'd put money on not being able to measure the difference in a real system. EnumType.ORDINAL is actually the default if you just do @Enumerated. I think most people (esp DBA's) tend to prefer the enum name in the DB. – Gareth Davis Jan 11 '11 at 08:44
  • 1
    How can I change the column length for these enums ? I tried adding the Column annotation but that does not get honoured? – Kannan Ekanath Sep 01 '11 at 11:15
  • 2
    You need to ask that as another question. – Gareth Davis Sep 01 '11 at 12:11
  • 2
    Use the STRING rather than ORDINAL as it allows you to add additional elements to the Enum irrespective of order. – Matthew Daumen May 13 '14 at 14:49
14

From the Hibernate documentation: http://www.hibernate.org/272.html

You can create a new typedef for each of your enums and reference the typedefs in the property tag.

Example Mapping - inline <type> tag

  <property name='suit'>
    <type name="EnumUserType">
      <param name="enumClassName">com.company.project.Suit</param>
    </type>
  </property>

Example Mapping - using <typedef>

  <typedef name="suit" class='EnumUserType'>
      <param name="enumClassName">com.company.project.Suit</param>
  </typedef>

  <class ...>
    <property name='suit' type='suit'/>
  </class>
Sirko
  • 72,589
  • 19
  • 149
  • 183
Craig
  • 1,406
  • 12
  • 24
  • Thanks. I was aware of that solution already. The problem is that it requires all your enums to use hibernate-internal types, which can result to issues if you are using the DAOs as DTOs as in my case. A better solution is actually described here: http://www.hibernate.org/273.html – Georgios Gousios Jan 06 '09 at 16:27
  • 1
    Note that in newer versions the parameter name is `enumClass` instead of `enumClassName`. – Ryan Ransford Aug 02 '11 at 15:25