JPAのQueryをMapオブジェクトに戻す


[size=xx-large]JPAのQueryをMapオブジェクトに戻す。
JPA 2.0では、ベントナイトManager.reate NativeQuery()を使って原生のSQL文を実行できます。しかし、私たちが照会した結果、対応するエンティティクラスがない場合、query.getResult List()はListを返します。つまり、1行あたりのデータは対象配列として返されます。
よくある使い方はこうです。
public void testNativeQuery(){
Query query = entityManager.createNativeQuery("select id, name, age from t_user");
List rows = query.getResultList();
for (Object row : rows) {
Object[] cells = (Object[]) row;
System.out.println("id = " + cells[0]);
System.out.println("name = " + cells[1]);
System.out.println("age = " + cells[2]);
}
}
このように使うとコードが非常に分かりにくくなります。0と表示されている要素は一体何なのか、検索語句を数えないと分かりません。また、検索語句が調整されると、Javaコードも調整されます。この時に戻ってきたのがMapだったら、もっとはっきり使えると思います。
残念なことに、JPAのAPIではこのような設定は提供されていません。実際、多くのJPAの下の実装は、Mapオブジェクトに戻ることをサポートしています。たとえば:
Eclipselinkのquery.setHit(QueryHits.RESULTYPE、ResultType.Map);
Hyberrateの.sets Result Trans former(Trans formers.ALIA Scuutont TYu MAP)
だから、もし私達がMapに戻りたいならば、そして下の階があるJPAの実現の時に私達は退くことができて、その次に、実現の特性を犠牲にして私達の需要を満たします:
public void testNativeQuery(){
Query query = entityManager.createNativeQuery("select id, name, age from t_user");
query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List rows = query.getResultList();
for (Object obj : rows) {
Map row = (Map) obj;
System.out.println("id = " + row.get("ID"));
System.out.println("name = " + row.get("NAME"));
System.out.println("age = " + row.get("AGE"));
}
}
ここで注意したいのは、Mapを使うのはObject配列を使うより効率が低いということです。ですから、性能の低下が許容範囲内にあるかどうかを見ます。また、私のHibernate 4.2.xの環境下では、元のSQLに大文字か小文字を書いても、戻ってくるフィールド名はすべて大文字です。もちろん、カスタムのResultTransformerでフィールド名を一定の処理してもいいです。自分の必要なPOJOに戻ることもできます。