【发布时间】: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