亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JPA:如何將本機查詢結果集轉換為POJO類集合

JPA:如何將本機查詢結果集轉換為POJO類集合

海綿寶寶撒 2019-07-22 15:48:30
JPA:如何將本機查詢結果集轉換為POJO類集合我在我的項目中使用JPA。我來到了一個查詢,在這個查詢中,我需要對五個表進行聯接操作。因此,我創建了一個本地查詢,它返回五個字段?,F在,我想將結果對象轉換為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類?
查看完整描述

3 回答

?
明月笑刀無情

TA貢獻1828條經驗 獲得超4個贊

JPA提供了一個SqlResultSetMapping,這使您可以將來自本機查詢的任何返回映射到實體中。

JPA1.0不允許映射到非實體類。僅在JPA 2.1 a中建筑成果已添加以映射java類的返回值。

另外,對于OP獲取計數的問題,應該可以用一個單獨的結果集映射來定義結果集映射。ColumnResult


查看完整回答
反對 回復 2019-07-22
?
一只甜甜圈

TA貢獻1836條經驗 獲得超5個贊

我找到了幾個解決辦法。

使用映射實體(JPA2.0)

使用JPA2.0不可能將原生查詢映射到POJO,只能通過實體完成。

例如:

Query query = em.createNativeQuery("SELECT name,age FROM jedi_table", Jedi.class);@SuppressWarnings("unchecked")List<Jedi> items = (List<Jedi>) query.getResultList();

但在這種情況下,Jedi,必須是映射的實體類。

避免此處未檢查的警告的另一種方法是使用命名的本機查詢。因此,如果我們在實體中聲明本機查詢

@NamedNativeQuery(
 name="jedisQry", 
 query = "SELECT name,age FROM jedis_table", 
 resultClass = Jedi.class)

然后,我們可以簡單地做:

TypedQuery<Jedi> query = em.createNamedQuery("jedisQry", Jedi.class);List<Jedi> items = query.getResultList();

這是比較安全的,但我們仍然被限制使用映射的實體。

人工映射

我試驗過的一個解決方案(在JPA2.1到來之前)是使用一點反射對POJO構造函數進行映射。

public static <T> T map(Class<T> type, Object[] tuple){
   List<Class<?>> tupleTypes = new ArrayList<>();
   for(Object field : tuple){
      tupleTypes.add(field.getClass());
   }
   try {
      Constructor<T> ctor = type.getConstructor(tupleTypes.toArray(new Class<?>[tuple.length]));
      return ctor.newInstance(tuple);
   } catch (Exception e) {
      throw new RuntimeException(e);
   }}

該方法基本上接受一個元組數組(由本機查詢返回),并通過查找具有相同數目的字段和相同類型的構造函數,將其映射到提供的POJO類。

然后我們可以使用方便的方法,例如:

public static <T> List<T> map(Class<T> type, List<Object[]> records){
   List<T> result = new LinkedList<>();
   for(Object[] record : records){
      result.add(map(type, record));
   }
   return result;}public static <T> List<T> getResultList(Query query, Class<T> type){
  @SuppressWarnings("unchecked")
  List<Object[]> records = query.getResultList();
  return map(type, records);}

我們可以簡單地使用這種技術,如下所示:

Query query = em.createNativeQuery("SELECT name,age FROM jedis_table");List<Jedi> 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<Jedi> samples = query.getResultList();

當然,在這種情況下Jedi不需要是映射的實體??梢允瞧胀ǖ腜OJO。

使用XML映射

我是那些發現添加所有這些的人之一@SqlResultSetMapping在我的實體中非常具有侵入性,而且我特別不喜歡實體中命名查詢的定義,因此,我也可以在META-INF/orm.xml檔案:

<named-native-query name="GetAllJedi" result-set-mapping="JediMapping">
    <query>SELECT name,age FROM jedi_table</query></named-native-query><sql-result-set-mapping name="JediMapping">
        <constructor-result target-class="org.answer.model.Jedi">
            <column name="name" class="java.lang.String"/>
            <column name="age" class="java.lang.Integer"/>
        </constructor-result>
    </sql-result-set-mapping>

這些都是我知道的解決辦法。如果我們可以使用JPA2.1,最后兩種方法是理想的。


查看完整回答
反對 回復 2019-07-22
  • 3 回答
  • 0 關注
  • 2209 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號