【问题标题】:Java JPA Hibernate SqlResultSetMapping AliasesJava JPA Hibernate SqlResultSetMapping 别名
【发布时间】:2017-01-07 16:54:23
【问题描述】:

在使用 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)
...

如果我在SqlResultSetMapping 中使用SELECT * 而不使用fields = @FieldResult...,代码会按预期工作,但我不能这样做,因为不同表中的列名相同。

我将通过手动将结果映射到实体来解决这个问题,因为我需要快速解决方案,但是如果我做错了什么或者 Hibernate 不支持我正在尝试做的事情,我会很高兴。书“Pro JPA 2”包含应该可以工作的非常相似的示例。

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

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

【问题讨论】:

  • 我今天才发现这个问题。以前我对 JPA 不太满意,因为我对 JPQL 的低表达性感到非常失望(我觉得我经常需要本地查询),但是现在……这太戏剧化了!我必须列出 20 列,如果其中只有一列发生变化,我必须在 3 个地方修复它。这是一场灾难,也是我最初试图用 JPA + Annotations 解决的问题。为什么不只依赖顺序?名为“id”的第一列对应于具有“id”字段的第一个实体,下一列对应于下一个实体等。

标签: java postgresql hibernate jpa sqlresultsetmapping


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    看起来本机查询未映射到 SqlResultSetMapping。查询中的列比映射中的列多得多。您查询中的选定列必须与您的映射相匹配。

    【讨论】:

    • 看起来像。但是有 JPA 示例(例如在“Pro JPA 2”一书中)表明这是有效的 - 只有与实体字段不匹配的列名必须明确指定。我也尝试指定所有内容,但遇到了不同的问题。更不用说它看起来非常难看——大约 50 个字段中的每一个都需要指定 3 次(1. 在实体中,2. 在查询中,3. 在结果集映射中)。
    • 看这里:thoughts-on-java.org/result-set-mapping-basics 上面写着“查询需要返回实体和JPA实现的所有属性”
    • 我的查询确实返回了实体的所有属性。它们只是没有在映射中指定,因为 JPA 应该能够从实体中确定它们的名称。如原始帖子中所述,如果我未在映射中指定 any 字段(仅实体)并且不使用别名,则它可以正常工作。因此,JPA 显然能够建立列属性映射,但是一旦在“fields=..”中定义了单个异常,它就会停止使用它。
    • 这是一个假定工作示例,它使用与我的代码相同的原理:java2s.com/Code/Java/JPA/SqlResultsetMappingWithAlias.htm - 如果时间允许,我将对该主题进行更多测试。如果这行得通,那就太好了。
    • 您的Gatewayclass 是否具有在本机查询中选择的所有属性?
    【解决方案3】:

    你可以使用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());
      }`
      

    【讨论】:

    • 感谢您的回复,SELECT NEW 看起来通常很有用。但是在我的情况下,我需要使用本机查询,因为使用了自定义 DB 函数的 count()(它进一步使用另一个 DB 函数的输出作为输入)。
    猜你喜欢
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 2021-08-19
    • 2013-02-06
    • 2019-05-29
    • 2018-03-30
    • 2011-11-17
    • 2010-09-09
    相关资源
    最近更新 更多