私はいくつかの角度からこの質問に取り組んできました、そしてここに私の発見があります。警告:MyBatis-3.1.1を使用してこれらすべての調査を行ったため、以前のバージョンでは動作が異なっていた可能性があります。
まず、MyBatisにはEnumTypeHandler
が組み込まれています 。デフォルトでは、java列挙型をresultTypeまたはparameterTypeとして指定するときはいつでも、これがそのタイプを処理します。クエリの場合、データベースレコードをJava列挙型に変換しようとすると、EnumTypeHandlerは1つの引数のみを取り、その値に対応するJava列挙値を検索しようとします。
例はよりよく説明します。上記のクエリが2
を返すとします。 および"Ready"
引数として「Ready」を渡すと。その場合、エラーメッセージNo enum constant com.foo.Status.2
が表示されます。 。 SELECTステートメントの順序を逆にすると
SELECT ls.name, ls.id
その場合、エラーメッセージはNo enum constant com.foo.Status.Ready
です。 。 MyBatisが何をしているのか推測できると思います。 EnumTypeHandlerは、クエリから返された2番目の値を無視していることに注意してください。
クエリを
に変更しますSELECT UPPER(ls.name)
動作させます:Status.READY列挙型が返されます。
そこで次に、Status列挙型に対して独自のTypeHandlerを定義しようとしました。残念ながら、デフォルトのEnumTypeHandler
と同様に 、正しい列挙型を参照するために、両方ではなく、一方の値(idまたはname)しか取得できませんでした。したがって、データベースIDが上記でハードコーディングした値と一致しない場合は、不一致が発生します。データベースIDが常に列挙型で指定したIDと一致することを確認した場合、データベースから必要なのは名前(大文字に変換)だけです。
次に、賢くなり、MyBatis ObjectFactoryを実装し、int idとString名の両方を取得して、返すJava列挙型でそれらが一致することを確認すると思いましたが、MyBatisがObjectFactoryを呼び出さないため、機能しませんでした。 Java列挙型(少なくとも動作させることができませんでした)。
したがって、私の結論は、データベースの名前を列挙型定数名に一致させる必要がある限り、MyBatisのJava列挙型は簡単であるということです。組み込みのEnumTypeHandlerを使用するか、UPPER(name)を実行する場合は独自の名前を定義します。 SQLは、Java列挙型の名前と一致するのに十分ではありません。多くの場合、これで十分です。列挙された値は列のチェック制約であり、IDも含まれず、単一の値しか含まれないためです。名前だけでなくintIDも一致させる必要がある場合は、Java列挙型やデータベースエントリを設定するときにIDを手動で一致させます。
最後に、この実用的な例をご覧になりたい場合は、MyBatisの公案23をご覧ください: https://github.com/midpeter444/mybatis-koans 。私の解決策を見たいだけなら、completed-koans/koan23ディレクトリを見てください。また、Java列挙型を介してデータベースにレコードを挿入する例もあります。