2014-12-23 31 views
6

previsto Ho un enum con una lista di stati (per esempio)Valore del parametro non corrisponde tipo

enum State 
{ 
    UP, 
    DOWN, 
    RETRY 
}; 

La colonna nel mio database è di tipo enum. Quando provo ad eseguire una query di Hibernate impostando il parametro nella query utilizzando setParameter("keyword", State.RETRY);, ricevo l'errore di

Valore del parametro [RIPROVA] non corrisponde previsto tipo [package.name.State (n/a)]

Nel mio server di Glassfish 4.1 per il mio dominio. Sto usando Hibernate 4.3.6.

Nel guardare il codice sorgente per Hibernate, vedo l'errore si verifica a causa di linee 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 restituisce false e quindi ottengo il messaggio.

esso stampa la String equivalente del valore a causa di questa linea enum:

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

Scopo bind è convertito implicitamente al valore stringa chiamando il metodo toString sul Object che rappresenta il enum State.RETRY.

Quindi, come posso convincere Hibernate che State.RETRY è un'istanza di State?

Sembra Hibernate aggiornato per l'APP 2.1 spec che è più severa in questo commit da aprile 2013:

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

L'entità è annotato come segue:

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

Edit:

My RetryState enum viene caricato dal EarLibClassLoader. Mentre il Query viene caricato da URLClassLoader e lo EntityManager viene caricato da un caricatore di classi diverso.

+1

Mostraci meglio come hai mappare che "parola chiave" di proprietà della vostra entità tramite annotazione - dovrebbe essere '@ Enumerated' btw – Antoniossss

+0

@Antoniossss: Vedere la mia modifica – Brian

+1

Sei sicuro che lo stato 'stato privato', si riferisce al enum corretto? Potresti aver importato quello sbagliato? – Tom

risposta

0

Questo è stato fissato dal ponendo le classi con le annotazioni APP e le classi enum in/lib/applib directory dominio-dir. È necessario inserire queste classi in un JAR nella directory dominio-dir/lib/applib e quindi specificare il jar nel comando deploy con asadmin utilizzando --libraries jar1,jar2,etc. Non posizionare uno spazio dopo la virgola quando si elencano più file JAR.

Inoltre, ho avuto un JAR comune che aveva interfacce remote EJB, così ho dovuto rompere le mie classi JPA in un nuovo JAR e metterli nei miei applibs directory anche. Quindi inserisco il JAR con le interfacce EJB remote nella mia directory EAR \ lib.

I JAR nella lib /applibs directory vengono caricati dal URLClassLoader. I JAR in EAR \ lib vengono caricati dal EARLibClassLoader.

2

Credo che il problema principale è che si sta tentando di utilizzare un tipo di dati enum sul lato del database. Questo non è raccomandato perché spesso richiede un tipo di enum proprietario che potrebbe non essere ben supportato dall'implementazione JPA (ad esempio Hibernate). Vedere this answer su una domanda simile per alcuni dettagli.

Inoltre, con l'annotazione

@Enumerated(EnumType.String) 

lei sta dicendo che si desidera in modo esplicito, che il valore viene salvato come String nel database. Mi aspetto che ciò non funzioni se il tipo di colonna reale è un enumerato.Forse le modifiche al codice di Hibernate stanno cercando di prevenire questi problemi obbligandoti a utilizzare le colonne varchar o numero intero.

Possibili soluzioni:

A)

utilizzare una colonna varchar con @Enumerated(EnumType.String) o una colonna int con @Enumerated

B)

Si può cercare di specificare la colonna enum tramite l'annotazione

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

C)

Si può cercare per specificare la classe enum tramite un file di sospensione di mapping XML:

<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> 

Vedi anche:

+0

Stranamente quando utilizzo EntityManagerFactory, questo problema scompare. – Brian

-2

Nel mio caso, StatusTransaction è un Enum e lo stato della variabile è una stringa.

La soluzione mio problema ->StatusTransaction.valueOf(status)

Problemi correlati