Java JPA Hibernate SqlResultSetMapping别名

时间:2016-08-31 07:57:30

标签: java postgresql hibernate jpa sqlresultsetmapping

在使用JPA 2.1和Hibernate 4.3.11实现的Java应用程序中,我尝试使用SqlResultSetMapping将本机查询结果映射到实体。查询包括连接的两个具有相同列名的表,因此我需要使用别名并映射它们(此处描述的问题:http://www.tinesoft.com/java/be-aware-of-mutliple-result-mappings-in-jpa

为了简单起见,我将查询和实体缩减到最小,这仍然会导致问题。真实代码使用两个实体和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 *中使用fields = @FieldResult...而没有SqlResultSetMapping,则代码按预期工作,但我不能这样做,因为不同表中的列名相同。

我将通过手动将结果映射到实体来解决这个问题,因为我需要快速解决方案,但是知道我做错了什么或者Hibernate不支持我想做的事情会很棒。 Book&#34; Pro JPA 2&#34;包含非常相似的例子,它应该起作用。

更新:使用Hibernate 5.1.1(Spring 4.3.2)测试 - 结果相同

更新:看起来像多个答案中提到的所有列名都需要指定。这对我来说似乎是JPA / Hibernate的一个大问题 - 这些列名可以从实体派生,只需手动指定例外。相反,我需要编写3次列名(1.查询,2。结果集映射3.实体),这是丑陋且难以维护的。

3 个答案:

答案 0 :(得分:0)

看起来原生查询未映射到SqlResultSetMapping。查询中的列数比映射中的列数多。查询中的选定列必须与您的映射匹配。

答案 1 :(得分: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());
    }`
    

答案 2 :(得分:0)

我认为您需要明确指定所有@FieldResult,因为您的列名在两个表之间存在冲突。