I have an enum with a list of states (e.g.)
enum State
{
UP,
DOWN,
RETRY
};
The column in my database is of type enum. When I try to execute a Hibernate query by setting the parameter in the query using setParameter("keyword", State.RETRY);
, I receive the error of
Parameter value [RETRY] did not match expected type [package.name.State (n/a)]
In my Glassfish 4.1 server.log for my domain. I am using Hibernate 4.3.6.
In looking at the source code for Hibernate, I see the error occurs because of lines 958-960 in org.hibernate.jpa.spi.BaseQueryImpl
:
private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
if ( expectedType.isInstance( value ) ) {
return true;
}
...
return false;
}
isValidBindValue
returns false and thus I get the message.
It prints out the String
equivalent of the enum
value because of this line:
String.format("Parameter value [%s] did not match expected type [%s (%s)]",
bind,
parameterType.getName(),
extractName( temporalType )
)
The bind
object is implicitly converted to the String value by calling the toString
method on the Object
which represents the enum State.RETRY
.
So how I can I convince Hibernate that State.RETRY
is an instance of State
?
It looks like Hibernate updated to the JPA 2.1 spec which is more strict in this commit from April 2013:
https://github.com/hibernate/hibernate-orm/commit/84520cd6e36e9207c41528cf9311cae905a86425
The entity is annotated as follows:
@Basic(optional = false)
@Column(name = "state")
@Enumerated(EnumType.String)
private State state;
Edit:
My RetryState
enum is loaded by the EarLibClassLoader
. Whereas Query
is loaded by the URLClassLoader and the EntityManager
is loaded by a different class loader.
This was fixed by placing the classes with the JPA annotations and enum classes into the domain-dir/lib/applib directory. You have to place these classes in a JAR in the domain-dir/lib/applib directory and then specify the jar on the deploy command with asadmin using the --libraries jar1,jar2,etc
. Do not place a space after the comma when listing multiple JAR files.
Also, I had a common JAR that had EJB remote interfaces, so I had to break out my JPA classes into a new JAR and place them in my applibs directory also. I then put the JAR with the EJB remote interfaces into my EAR\lib directory.
The JARs in the lib/applibs directory are loaded by the URLClassLoader. The JARs in the EAR\lib are loaded by the EARLibClassLoader.