2

Hibernate 4.3.11実装でJPA 2.1を使用するJavaアプリケーションでは、SqlResultSetMappingネイティブクエリ結果をエンティティにマップするために使用しようとしています。クエリには、同じ列名を持つ結合された 2 つのテーブルが含まれているため、エイリアスを使用してそれらをマップする必要があります (ここで説明されている問題: http://www.tinesoft.com/java/be-aware-of-multiple-result-mappings-in- jpa )

質問を簡単にするために、クエリとエンティティを最小限に縮小しましたが、それでも問題が発生します。実際のコードでは、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)
...

SELECT *inなしfields = @FieldResult...で使用するとSqlResultSetMapping、コードは期待どおりに機能しますが、異なるテーブルに同じ列名があるため、それができません。

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

更新: Hibernate 5.1.1 (Spring 4.3.2) でテスト済み - 同じ結果

更新:複数の回答で言及されているように、すべての列名を指定する必要があるようです。これは、JPA/Hibernate の大きな問題のように思えます。これらの列名は、手動で指定された例外を除いて、エンティティから派生する可能性があります。代わりに、列名を 3 回 (1. クエリ、2. 結果セット マッピング、3. エンティティ) 記述する必要があり、見苦しく、維持が困難です。

4

3 に答える 3

0

使用できますSELECT NEW

  1. query で使用する必要があるすべての列を持つクラスを作成します。

    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());
    }`
    
于 2016-08-31T15:03:15.727 に答える
0

@FieldResult特に、2 つのテーブル間で競合する列名があるため、すべてを明示的に指定する必要があると思います。

于 2016-09-01T11:26:00.997 に答える