JPA:如何将本机查询结果集转换为POJO类集合

JPA:如何将本机查询结果集转换为POJO类集合

我在我的项目中使用JPA。

我来到了一个查询,在这个查询中,我需要对五个表进行联接操作。因此,我创建了一个本地查询,它返回五个字段。

现在,我想将结果对象转换为javaPOJO类,该类包含相同的五个字符串。

JPA中有任何方法直接将结果转换为POJO对象列表吗?

我想出了以下解决方案。

@NamedNativeQueries({  
    @NamedNativeQuery(  
        name = "nativeSQL",  
        query = "SELECT * FROM Actors",  
        resultClass = db.Actor.class),  
    @NamedNativeQuery(  
        name = "nativeSQL2",  
        query = "SELECT COUNT(*) FROM Actors",  
        resultClass = XXXXX) // <--------------- problem  })

现在结果类中,我们是否需要提供一个类,它是实际的JPA实体?或者我们可以将其转换为包含相同列名的任何JavaPOJO类?


海绵宝宝撒
浏览 2151回答 3
3回答

明月笑刀无情

JPA提供了一个SqlResultSetMapping,这使您可以将来自本机查询的任何返回映射到实体中。JPA1.0不允许映射到非实体类。仅在JPA 2.1 a中建筑成果已添加以映射java类的返回值。另外,对于OP获取计数的问题,应该可以用一个单独的结果集映射来定义结果集映射。ColumnResult

一只甜甜圈

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

相关分类

Java