我找到了几个解决办法。
使用映射实体(JPA2.0)
使用JPA2.0不可能将原生查询映射到POJO,只能通过实体完成。
例如:Query query = em.createNativeQuery("SELECT name,age FROM jedi_table", Jedi.class);@SuppressWarnings("unchecked")List items = (List) query.getResultList();
但在这种情况下,Jedi,必须是映射的实体类。
避免此处未检查的警告的另一种方法是使用命名的本机查询。因此,如果我们在实体中声明本机查询@NamedNativeQuery(
name="jedisQry",
query = "SELECT name,age FROM jedis_table",
resultClass = Jedi.class)
然后,我们可以简单地做:TypedQuery query = em.createNamedQuery("jedisQry", Jedi.class);List items = query.getResultList();
这是比较安全的,但我们仍然被限制使用映射的实体。
人工映射
我试验过的一个解决方案(在JPA2.1到来之前)是使用一点反射对POJO构造函数进行映射。public static T map(Class type, Object[] tuple){
List> tupleTypes = new ArrayList<>();
for(Object field : tuple){
tupleTypes.add(field.getClass());
}
try {
Constructor ctor = type.getConstructor(tupleTypes.toArray(new Class>[tuple.length]));
return ctor.newInstance(tuple);
} catch (Exception e) {
throw new RuntimeException(e);
}}
该方法基本上接受一个元组数组(由本机查询返回),并通过查找具有相同数目的字段和相同类型的构造函数,将其映射到提供的POJO类。
然后我们可以使用方便的方法,例如:public static List map(Class type, List records){
List result = new LinkedList<>();
for(Object[] record : records){
result.add(map(type, record));
}
return result;}public static List getResultList(Query query, Class type){
@SuppressWarnings("unchecked")
List records = query.getResultList();
return map(type, records);}
我们可以简单地使用这种技术,如下所示:Query query = em.createNativeQuery("SELECT name,age FROM jedis_table");List jedis = getResultList(query, Jedi.class);
带有@SqlResultSetmap的JPA2.1
随着JPA2.1的到来,我们可以使用@SqlResultSetmap注释来解决这个问题。
我们需要声明实体中某个地方的结果集映射:@SqlResultSetMapping(name="JediResult", classes = {
@ConstructorResult(targetClass = Jedi.class,
columns = {@ColumnResult(name="name"), @ColumnResult(name="age")})})
然后我们就这么做了:Query query = em.createNativeQuery("SELECT name,age FROM jedis_table", "JediResult");@SuppressWarnings("unchecked")List samples = query.getResultList();
当然,在这种情况下Jedi不需要是映射的实体。可以是普通的POJO。
使用XML映射
我是那些发现添加所有这些的人之一@SqlResultSetMapping在我的实体中非常具有侵入性,而且我特别不喜欢实体中命名查询的定义,因此,我也可以在META-INF/orm.xml档案:
SELECT name,age FROM jedi_table
这些都是我知道的解决办法。如果我们可以使用JPA2.1,最后两种方法是理想的。