Java JPA Hibernate SqlResultSetMap别名

yeotifhr  于 2022-11-14  发布在  Java
关注(0)|答案(3)|浏览(120)

在使用JPA 2.1和Hibernate 4.3.11实现的Java应用程序中,我尝试使用SqlResultSetMapping将本地查询结果Map到实体。查询包括具有相同列名的联接的两个表,因此我需要使用别名并Map它们(此处描述了问题:(第10页)
为了简化问题,我将查询和实体压缩到最小,但这仍然会导致问题。真实的代码使用两个实体和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(Sql结果集Map):

@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)
...

如果我在SqlResultSetMapping中使用SELECT *而不使用fields = @FieldResult...,代码可以按预期工作,但由于不同表中的列名相同,我无法这样做。
我将通过手动将结果Map到实体来解决这个问题,因为我需要快速的解决方案,但如果知道我做错了什么或者Hibernate不支持我正在尝试做的事情,那就太好了。Book“Pro JPA 2”包含了非常类似的示例,应该可以工作。
更新:使用Hibernate 5.1.1(Spring 4.3.2)进行测试-结果相同
更新:看起来所有的列名都需要指定,就像在多个答案中提到的那样。对我来说,这似乎是JPA/Hibernate的一个大问题-那些列名可以从实体中派生出来,只有手动指定的例外。相反,我需要写列名3次(1.查询,2.结果集Map,3.实体),这很难看,很难维护。

sy5wg1nm

sy5wg1nm1#

我认为您需要显式指定所有的@FieldResult,特别是因为两个表之间的列名存在冲突。

thtygnil

thtygnil2#

本机查询似乎未Map到SqlResultSetMapping。查询中的列数比Map中的列数多得多。查询中选定的列必须与Map匹配。

093gszye

093gszye3#

您可以使用SELECT NEW
1.创建一个类,使所有需要的列都在查询中使用。

package dz.my;

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
     ...... 

    }

1.使用查询

Query query = em.createQuery("SELECT NEW dz.my.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());
}`

相关问题