Parameter value does not match expected type

I have an enumeration with a list of states (for example)

enum State { UP, DOWN, RETRY }; 

The column in my database is of type enum. When I try to execute a Hibernate request by setting a parameter in the request using setParameter("keyword", State.RETRY); , I get an error

The value of the [RETRY] โ€‹โ€‹parameter does not match the expected type [package.name.State (n / a)]

In my Glassfish 4.1 server.log for my domain. I am using Hibernate 4.3.6.

When viewing the source code for Hibernate, I see that the error is due to 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 so I get the message.

It returns the String equivalent of enum because of this string:

 String.format("Parameter value [%s] did not match expected type [%s (%s)]", bind, parameterType.getName(), extractName( temporalType ) ) 

The bind object is implicitly converted to a String value by calling the toString method on the Object , which represents enum State.RETRY .

So, how can I convince Hibernate that State.RETRY is an instance of State ?

Hibernate seems to have been updated to the JPA 2.1 specification, which has been stricter in this commit since April 2013:

https://github.com/hibernate/hibernate-orm/commit/84520cd6e36e9207c41528cf9311cae905a86425

An object is annotated as follows:

 @Basic(optional = false) @Column(name = "state") @Enumerated(EnumType.String) private State state; 

Edit:

My RetryState enum is loaded by EarLibClassLoader . While Query loads URLClassLoader, and EntityManager loads with another class loader.

+6
source share
2 answers

This has been fixed by placing classes with JPA annotations and enumerated classes in the domain-dir / lib / applib directory . You must put these classes in the JAR in the domain-dir / lib / applib directory , and then specify the deploy command bank using asadmin using --libraries jar1,jar2,etc Do not place a space after the decimal point when listing multiple JAR files.

Also, I had a regular JAR with remote EJB interfaces, so I had to split the JPA classes into a new JAR and put them in the applibs directory. Then I put the JAR with the remote EJBs in the EAR \ lib directory.

JARs in the lib / applibs directory are loaded by URLClassLoader . JARs in EAR \ lib are loaded by EARLibClassLoader .

0
source

I assume that the main problem is that you are trying to use the enum data type on the database side. This is not recommended because it often requires its own type of enumeration, which may not be sufficiently supported by the JPA implementation (e.g. Hibernate). See this answer for a similar question for some details.

Next, with annotation

 @Enumerated(EnumType.String) 

you say that you explicitly want the value to be stored as a string in the database. I would expect this to not work if the actual column type is some enumeration. Perhaps Hibernate code changes are trying to prevent these problems by forcing you to use varchar or integer columns.

Possible solutions:

A)

Use varchar column with @Enumerated(EnumType.String) or int column with @Enumerated

B)

You can try to specify an enumeration column using annotation

 @Basic(optional = false) @Column(name = "state", columnDefinition = "enum('UP','DOWN','RETRY')") @Enumerated(EnumType.String) private State state; 

WITH)

You can try to specify your enumeration class through an XML sleep mode mapping file:

 <property name="type" column="type" not-null="true"> <type name="org.hibernate.type.EnumType"> <param name="enumClass">package.name.State</param> <param name="type">12</param> <!-- 12 is java.sql.Types.VARCHAR --> </type> </property> 

See also:

+2
source

Source: https://habr.com/ru/post/980083/


All Articles