Skip to content
Advertisement

Hibernate mapping between PostgreSQL enum and Java enum

Background

  • Spring 3.x, JPA 2.0, Hibernate 4.x, Postgresql 9.x.
  • Working on a Hibernate mapped class with an enum property that I want to map to a Postgresql enum.

Problem

Querying with a where clause on the enum column throws an exception.

JavaScript

Code (heavily simplified)

SQL:

JavaScript

Hibernate mapped class:

JavaScript

Java that calls the query:

JavaScript

Hibernate xml query:

JavaScript

Troubleshooting

  • Querying by id instead of the enum works as expected.
  • Java without database interaction works fine:

    JavaScript
  • createQuery instead of having the query in XML, similar to the findByRating example in Apache’s JPA and Enums via @Enumerated documentation gave the same exception.
  • Querying in psql with select * from move where direction = 'LEFT'; works as expected.
  • Hardcoding where direction = 'FORWARD' in the query in the XML works.
  • .setParameter("direction", direction.name()) does not, same with .setString() and .setText(), exception changes to:

    JavaScript

Attempts at resolution

  • Custom UserType as suggested by this accepted answer https://stackoverflow.com/a/1594020/1090474 along with:

    JavaScript
  • Mapping with Hibernate’s EnumType as suggested by a higher rated but not accepted answer https://stackoverflow.com/a/1604286/1090474 from the same question as above, along with:

    JavaScript

    With and without the two second parameters, after seeing https://stackoverflow.com/a/13241410/1090474

  • Tried annotating the getter and setter like in this answer https://stackoverflow.com/a/20252215/1090474.
  • Haven’t tried EnumType.ORDINAL because I want to stick with EnumType.STRING, which is less brittle and more flexible.

Other notes

A JPA 2.1 Type Converter shouldn’t be necessary, but isn’t an option regardless, since I’m on JPA 2.0 for now.

Advertisement

Answer

HQL

Aliasing correctly and using the qualified property name was the first part of the solution.

JavaScript

Hibernate mapping

@Enumerated(EnumType.STRING) still didn’t work, so a custom UserType was necessary. The key was to correctly override nullSafeSet like in this answer https://stackoverflow.com/a/7614642/1090474 and similar implementations from the web.

JavaScript

Detour

implements ParameterizedType wasn’t cooperating:

JavaScript

so I wasn’t able to annotate the enum property like this:

JavaScript

Instead, I declared the class like so:

JavaScript

with a constructor:

JavaScript

which, unfortunately, means any other enum property similarly mapped will need a class like this:

JavaScript

Annotation

Annotate the property and you’re done.

JavaScript

Other notes

  • EnhancedUserType and the three methods it wants implemented

    JavaScript

    didn’t make any difference I could see, so I stuck with implements UserType.

  • Depending on how you’re using the class, it might not be strictly necessary to make it postgres-specific by overriding nullSafeGet in the way the two linked solutions did.
  • If you’re willing to give up the postgres enum, you can make the column text and the original code will work without extra work.
Advertisement