州のリストを含む列挙型があります(例)
_enum State
{
UP,
DOWN,
RETRY
};
_
私のデータベースの列は列挙型です。 setParameter("keyword", State.RETRY);
を使用してクエリのパラメータを設定してHibernateクエリを実行しようとすると、次のエラーが発生します。
パラメータ値[RETRY]が予期されたタイプと一致しませんでした[package.name.State(n/a)]
私のドメインのGlassfish4.1server.log。 Hibernate4.3.6を使用しています。
Hibernateのソースコードを見ると、_org.hibernate.jpa.spi.BaseQueryImpl
_の行958-960が原因でエラーが発生していることがわかります。
_private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
if ( expectedType.isInstance( value ) ) {
return true;
}
...
return false;
}
_
isValidBindValue
はfalseを返すため、メッセージが表示されます。
次の行があるため、String
値と同等のenum
が出力されます。
_String.format("Parameter value [%s] did not match expected type [%s (%s)]",
bind,
parameterType.getName(),
extractName( temporalType )
)
_
bind
オブジェクトは、_enum State.RETRY
_を表すtoString
でObject
メソッドを呼び出すことにより、暗黙的に文字列値に変換されます。
では、どうすれば_State.RETRY
_がState
のインスタンスであることをHibernateに納得させることができますか?
HibernateがJPA2.1仕様に更新されたようです。これは、2013年4月からのこのコミットでより厳格です。
https://github.com/hibernate/hibernate-orm/commit/84520cd6e36e9207c41528cf9311cae905a86425
エンティティには次のように注釈が付けられます。
_@Basic(optional = false)
@Column(name = "state")
@Enumerated(EnumType.String)
private State state;
_
編集:
私のRetryState
列挙型はEarLibClassLoader
によってロードされます。一方、Query
はURLClassLoaderによってロードされ、EntityManager
は別のクラスローダーによってロードされます。
これは、JPAアノテーションと列挙型クラスを持つクラスをdomain-dir/lib/applibディレクトリに配置することで修正されました。これらのクラスをdomain-dir/lib/applibディレクトリのJARに配置し、asadminを使用してdeployコマンドでjarを指定する必要があります。 --libraries jar1,jar2,etc
。複数のJARファイルをリストする場合は、コンマの後にスペースを入れないでください。
また、EJBリモートインターフェイスを持つ共通のJARがあったため、JPAクラスを新しいJARに分割し、それらをapplibsに配置する必要がありました。 =ディレクトリも。次に、EJBリモートインターフェイスを備えたJARをEAR\libディレクトリに配置します。
lib/applibsディレクトリ内のJARは、URLClassLoaderによってロードされます。 =。 EAR\lib内のJARは、EARLibClassLoaderによってロードされます。
主な問題は、データベース側で列挙型データ型を使用しようとしていることだと思います。これは、JPA実装(Hibernateなど)で十分にサポートされていない可能性のある独自の列挙型を必要とすることが多いため、お勧めしません。詳細については、同様の質問について この回答 を参照してください。
さらに、注釈付き
_@Enumerated(EnumType.String)
_
明示的に必要なこと、値がデータベースに保存されることを意味します文字列として。実際の列タイプがいくつかの列挙型である場合、これは失敗すると予想されます。たぶん、Hibernateコードの変更は、varcharまたはinteger列のいずれかを使用するように強制することにより、これらの問題を防止しようとしています。
考えられる解決策:
A)
@Enumerated(EnumType.String)
でvarchar列を使用するか、_@Enumerated
_でint列を使用します
B)
アノテーションを介して列挙型列を指定してみることができます
_@Basic(optional = false)
@Column(name = "state", columnDefinition = "enum('UP','DOWN','RETRY')")
@Enumerated(EnumType.String)
private State state;
_
C)
HibernateXMLマッピングファイルを介して列挙型クラスを指定してみることができます。
_<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>
_
参照: