2016-08-31 4 views
2

。クエリには同じ列名を持つ2つのテーブルが結合されているため、エイリアスを使用してマップする必要があります(http://www.tinesoft.com/java/be-aware-of-mutliple-result-mappings-in-jpaの説明を参照)JavaのJPA HibernateはSqlResultSetMappingエイリアス

質問を簡単にするため、質問とエンティティを最小限に縮小しました。実コードは2つのエンティティとDB関数を使用します。これが、JPQLではなくネイティブクエリを使用する理由です。

ゲートウェイ・エンティティ:

@Entity 
public class Gateway implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 
    private Integer active; 
    ... 
    @Column(name = "activation_code") 
    private String activationCode; 
    ... 
} 

SqlResultSetMapping:

@SqlResultSetMapping(
     name = "GatewayWithLoc", 
     entities = { 
      @EntityResult(entityClass = Gateway.class , fields =  @FieldResult(name = "id", column = "gw_id")) 
     } 
) 

問合せ:

Query query = em.createNativeQuery("SELECT gw.id AS gw_id, ..., active, activation_code, ... FROM gateway gw", "GatewayWithLoc"); 
List<Object[]> rows = query.getResultList(); 

例外:

Caused by: org.postgresql.util.PSQLException: The column name activati2_1_0_ was not found in this ResultSet. 
at org.postgresql.jdbc2.AbstractJdbc2ResultSet.findColumn(AbstractJdbc2ResultSet.java:2803) 
... 

私はSqlResultSetMappingfields = @FieldResult...なしSELECT *を使用する場合は、期待通りのコードは動作しますが、私はので、異なるテーブルで同じカラム名のことを行うことはできません。私は迅速なソリューションを必要と

は、私は、エンティティへの手動マッピングの結果によってこの問題を解決しますが、私が何か間違ったことをやっているかどうかを知るのは素晴らしいだろうか、Hibernateは私が何をしようとしています何をサポートしていません。本「Pro JPA 2」には、動作するはずの非常によく似た例が含まれています。

更新:Hibernateは5.1.1でテスト(春4.3.2) - 同じ結果

更新:すべての列名を複数回答で述べたように指定する必要があるように見えます。これらのカラム名を手動で指定されたばかりの例外を除いて、エンティティから導出することができ - これは私には休止状態/ JPAの大きな問題のように思えます。代わりに、私はカラム名を3回書く必要があります(1.クエリー、2.結果セットマッピング3.エンティティ)。ネイティブクエリがSqlResultSetMappingにマップされないように

+0

私は今日だけは、この問題を発見しました。以前はJPAに満足していませんでした.JPQLの表現力が低いことにかなり失望していました(私はネイティブクエリーの方法が必要なのですが)。しかし今、これは...劇的です!私は20列を列挙しなければならず、それらのうちの1つだけが変更されれば、3つの場所で修正する必要があります。これは災害であり、私はJPA +アノテーションで最初に解決しようとしていた問題です。なぜ注文に依存しないのですか? 'id'という名前の最初の列は、 'id'フィールド、次のエンティティへの次の列などを持つ最初のエンティティに対応します。 –

答えて

0

を使用して、私はあなたが2つのテーブル間の矛盾している列の名前を持っている、特に以来、明示的にすべての@FieldResultを指定する必要があると思います。

0

が見えます。あなたのクエリでは、あなたのマッピングよりも多くのカラムがあります。クエリの選択した列は、マッピングと一致する必要があります。

+0

それはそのように見えます。しかし、それが有効であることを示すJPAの例(例えば書籍 "Pro JPA 2")があります。エンティティフィールドと一致しない列名だけが明示的に指定されなければなりません。私もすべてを指定しようとしましたが、別の問題が発生しました。言い換えれば、非常に醜いとは言えません。〜50フィールドのそれぞれを3回指定する必要がありました(エンティティで1.、クエリで2.、結果セットマッピングで3.)。 – Miha

+0

はこちらをご覧:http://www.thoughts-on-java.org/result-set-mapping-basics/マイクエリ –

+0

「クエリは、エンティティのすべてのプロパティとJPAの実装を返す必要がある」が記載されていますエンティティのすべてのプロパティを返します。 JPAはエンティティから名前を判別できるはずなので、マッピングでは指定されていません。元の投稿で述べたように、マッピングに*フィールドを指定せず(エンティティのみ)、エイリアスを使用しないとうまくいきます。したがってJPAは明らかに列<>特性マッピングを確立することができますが、 "fields = .."で単一の例外が定義されるとすぐに使用を停止します。私は時が許せトピックに関するより多くのテストを行います - http://www.java2s.com/Code/Java/JPA/SqlResultsetMappingWithAlias.htm: – Miha

0

あなたはSELECT NEWを使用することができます。

  1. は、クラスを作成し、クエリ内のすべての列に必要な使用しています。

    package dz.immo; 
    
    public class GatewayGatewayWithLoc { 
        private Integer idGw; 
        private Integer activeGw; 
        private Integer idGwWl; 
        private Integer activeGwWl; 
    
         public GatewayGatewayWithLoc(Integer idGw, Integer activeGw, Integer idGwWl, Integer activeGwWl) { 
          this.idGw = idGw; 
          this.activeGw = activeGw; 
          this.idGwWl = idGwWl; 
          this.activeGwWl = activeGwWl; 
         } 
         .... 
        // getter and setter 
        ...... 
    
        } 
    
  2. クエリ

    Query query = em.createQuery("SELECT NEW dz.immo.GatewayGatewayWithLoc(gw.id, gw.active, gwwl.id, gwwl.active) FROM Gateway gw ,GatewayGatewayWithLoc gwwl WHERE ..."); List<GatewayGatewayWithLoc> liste = query.getResultList(); // display the answer for (GatewayGatewayWithLoc gwgw : liste) { System.out.println("GatewayGatewayWithLoc : " + gwgw.getIdGw() + " " + gwgw.getActiveGw()+ " " + gwgw.getIdGwWl()+ " " + gwgw.getActiveGwWl()); }

+0

感謝をid''「フィールドを'持つすべてのエンティティのid''を」という名前の最初の列を選択し、NEWは、一般的に有用になります。SELECT 。しかし、私の場合は、カスタムDB関数(他のDB関数の出力を入力として使用する)でcount()としてネイティブクエリを使用する必要があります。 – Miha