2017-12-15 10 views
2

に結果をマップしますjavax.persistence.PersistenceException:org.hibernate.MappingException:不明なエンティティ:it。*。PoolStateResult |使用DTO(ないエンティティ)

<dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
      <version>1.5.8.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-data-jpa</artifactId> 
      <version>1.5.8.RELEASE</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <version>1.5.8.RELEASE</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.12</version> 
      <scope>test</scope> 
     </dependency> 

     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>${spring.version}</version> 
      <scope>test</scope> 
     </dependency> 
    </dependencies> 

これは私のDTOです。 DB上のエンティティではありません。私は、これはDAO

の内容
Query q = em.createNativeQuery(" SELECT p.start_validity_date as startDateValidate, " 
      + " p.end_validity_date as endDateValidate, " 
      + " (SELECT count(*) from POOL_CODES p WHERE p.id_pool = :poolCode) as totalCodes, " 
      + " (SELECT count(*) " 
      + " from VOUCHER v " 
      + " WHERE v.id_reference_pool = :poolCode " 
      + " AND v.status = 'ASSEGNATO') as assignedCodes, " 
      + " (SELECT count(*) " 
      + " from VOUCHER v, POOL_CODES p " 
      + " WHERE v.id_reference_pool = p.id_pool " 
      + " AND v.id_reference_pool = :poolCode " 
      + " AND v.status = 'ASSEGNATO' " 
      + " and p.end_validity_date < sysdate) as availableCodes " 
      + " from POOL_CODES p " 
      + " WHERE p.id_pool = :poolCode",PoolStateResult.class); 

    q.setParameter("poolCode", "poolCode"); 
    return (PoolStateResult) q.getSingleResult();  

あるのみマッピング

public class PoolStateResult { 

    private Integer totalCodes; 
    private Integer assignedCodes; 
    private Integer availableCodes; 

    private Date startDateValidate; 
    private Date endDateValidate; 

constructors 
getters and setters 

のためにそれを使用したい私は、これは例外

javax.persistence.NoResultException: No entity found for query 
    at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:532) 
であるコンフィギュレーションクラスに

entityManagerFactory.setPackagesToScan(
       env.getProperty("entitymanager.packages.to.scan"), 

をこのパッケージを追加します

すべてのエンティティテーブルと同じように自動的にマッピングを強制する方法、またはhibernateを使用する唯一の方法は、これらのタイプのクエリに対してマッピングを書き込むことです。 これは、Hibernateを使用してエンティティではないJavaオブジェクトをマップする最善の方法ですか?

@SqlResultSetMapping(
       name="getPoolStateResult", 
       classes={ 
        @ConstructorResult(
         targetClass=PoolStateResult.class, 
         columns={ 
          @ColumnResult(name="totalCodes", type=Integer.class), 
          @ColumnResult(name="assignedCodes", type=Integer.class), 
          @ColumnResult(name="availableCodes", type=Integer.class), 
          @ColumnResult(name="startDateValidate", type=Date.class), 
          @ColumnResult(name="endValidityDate", type=Date.class) 
          } 
       ) 
       } 
      ) 

次に、この場合、休止状態の利点はどこですか?

おかげ

+0

問題の説明で言及した例外は、マッピングに関する問題ではなく、 '' 'q.getSingleResult();' 'を使用することに関連しています。ご覧のとおり、選択基準に一致するレコードがデータベースにない場合、このメソッドは例外をスローします。 – Kamil

+0

私はデータベースに結果があると確信しています。 Dbでクエリを実行すると動作します。 マッピングITを書くこともできます。 – Angelo

+0

'p。end_validity_date as endValidityDate' - あなたのDTOにendValidityDateと呼ばれるメンバー変数はありません。これが問題だろうか? – Cashbee

答えて

1

JPAとHibernateは、マッピング情報なしでクエリ結果をDTOに自動的にマッピングすることはできません。プログラムで結果をマップするか、例のようにコンストラクタ呼び出しを@SqlResultSetMappingに定義します。

結果をエンティティにマップする必要がある場合は、この操作を行う必要はありません。 Hibernateは次に、エンティティーのマッピング定義を使用して照会結果をマップしようとします。したがって、クエリ結果はすべてのエンティティ属性を返す必要があり、エンティティマッピングで使用するのと同じ名前を持つ必要があります。詳細については、series of blog posts about @SqlResultMappingで説明しました。

このようなクエリにHibernateを使用する利点について: これがトランザクションで唯一のデータベース対話である場合、Hibernateはあなたに何の利点も提供しません。しかし、このクエリをHibernateセッション内で使用することができるため、Hibernateがそのセッションで実行する他のすべての操作と同じトランザクション内で使用できます。

+0

ありがとうございます。 @SqlResultSetMappingについて: EclipseLink - >クラスパスの任意のクラスに配置します。 Hibernate - > @Entityで注釈が付けられたどのクラスにでも置くことができます。 これは正しいですか? – Angelo

+0

EclipseLinkについてはわかりませんが、Hibernateにとっては正しいことです。注釈をpackage-info.javaまたは非エンティティクラスに入れると、アノテーションは無視されます –

0

は少しあなたのクエリの作成を変更してください:

1)選択リスト

String queryString = 
     "SELECT new com.mypackage.PoolStateResult(" 
      + "p.start_validity_date as startDateValidate, " 
      + " p.end_validity_date as endValidityDate, " 
      + " (SELECT count(*) from POOL_CODES p WHERE p.id_pool = :poolCode) as totalCodes, " 
      + " (SELECT count(*) " 
      + ")" 
      + " from VOUCHER v " 
       ... 

2にNEW package.Classを追加しますが)は、先のcreateNativeQueryメソッドを使用します2番目のパラメータとしてSQLマッピング名を渡します。

em.createNativeQuery(queryString, "getPoolStateResult"); 
+0

こんにちは、クエリを変更しなくても、マッピングITを書くことができます。問題は、マッパーを書くことなく同じ結果を得ることができますが、DTO PoolStateResult(エンティティなど)を使用する場合のみです – Angelo

+0

: –

+0

クエリで.setResultTransformer(Transformers.aliasToBean(PoolStateResult .class))を設定してみてください。 setResultTransformerは廃止予定であるか、または休止状態5に存在しません – Angelo

関連する問題