Java JPA Hibernate SqlResultsMapping别名
在使用JPA2.1和Hibernate 4.3.11实现的Java应用程序中,我尝试使用Java JPA Hibernate SqlResultsMapping别名,java,postgresql,hibernate,jpa,sqlresultsetmapping,Java,Postgresql,Hibernate,Jpa,Sqlresultsetmapping,在使用JPA2.1和Hibernate 4.3.11实现的Java应用程序中,我尝试使用SqlResultSetMapping将本机查询结果映射到实体。查询包含两个具有相同列名的联接表,所以我需要使用别名并映射它们(此处描述的问题:) 为了简化问题,我将查询和实体缩减到最小,这仍然会导致问题。真正的代码使用两个实体和DB函数,这就是使用本机查询而不是JPQL的原因 网关实体: @Entity public class Gateway implements Serializable { @
SqlResultSetMapping
将本机查询结果映射到实体。查询包含两个具有相同列名的联接表,所以我需要使用别名并映射它们(此处描述的问题:)
为了简化问题,我将查询和实体缩减到最小,这仍然会导致问题。真正的代码使用两个实体和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;
...
}
SqlResultsMapping:
@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();
如果我在SqlResultSetMapping
中使用SELECT*
而不使用fields=@FieldResult…
,代码将按预期工作,但由于不同表中的列名相同,我无法这样做
我将通过手动将结果映射到实体来解决这个问题,因为我需要快速的解决方案,但是如果知道我是否做错了什么,或者Hibernate不支持我尝试做的事情,那就太好了。《Pro JPA 2》一书中包含了非常类似的例子,应该是可行的
更新:使用Hibernate 5.1.1(Spring 4.3.2)进行测试-结果相同
更新:看起来所有的列名都需要按照多个答案中提到的那样指定。对我来说,这似乎是JPA/Hibernate的一个大问题——这些列名可以从实体派生,只有手动指定的异常。相反,我需要写3次列名(1.query,2.result set mapping,3.entity),这很难看而且很难维护。看起来本机查询没有映射到
SqlResultSetMapping
。查询中的列比映射中的列多得多。查询中选定的列必须与映射匹配。您可以使用选择新的:
创建一个类,该类包含查询中需要使用的所有列
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
......
}
使用查询
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());
}`
Query Query=em.createQuery(“从网关gw、网关WithLoc gwwl WHERE…)中选择新的dz.immo.GatewayGatewayWithLoc(gw.id、gw.active、gwwl.id、gwwl.active));
List liste=query.getResultList();
//显示答案
用于(带LOC gwgw的网关网关:列表){
System.out.println(“GatewayGatewayWithLoc:”+gwgw.getIdGw()+“”+gwgw.getActiveGw()+“”+gwgw.getIdGwWl()+“”+gwgw.getActiveGwWl());
}`
我认为您需要显式指定所有的@FieldResult
,尤其是因为两个表之间的列名冲突。看起来是这样的。但是有一些JPA示例(例如,在“Pro JPA 2”一书中)表明这是有效的-只有与实体字段不匹配的列名必须明确指定。我还试图详细说明所有内容,但遇到了不同的问题。更不用说它看起来非常难看-大约50个字段中的每一个都需要指定3次(1.在实体中,2.在查询中,3.在结果集映射中)。看看这里:有这样一句话:“查询需要返回实体的所有属性,JPA实现”我的查询确实返回实体的所有属性。它们只是没有在映射中指定,因为JPA应该能够从实体中确定它们的名称。正如在最初的文章中提到的,如果我在映射中不指定任何字段(仅实体)并且不使用别名,它就可以正常工作。因此,JPA显然能够建立ColumnProperty映射,但一旦在“fields=…”中定义了一个异常,它就会停止使用它。下面是一个假定的工作示例,它使用了与我的代码相同的原则:-如果时间允许,我将在这个主题上做更多的测试。如果这能起作用,那就太好了。您的Gateway
类是否具有本机查询中选择的所有属性?感谢您的回答,选择新外观通常很有用。然而,在我的例子中,我需要在使用自定义DB函数时使用本机查询count()(它进一步使用另一个DB函数的输出作为输入)。我以前对JPA不太满意,因为我对JPQL的lowe表现力感到非常失望(我觉得我经常需要原生查询方式),但现在这。。。太戏剧性了!我必须列出20列,如果其中只有一列发生了变化,我必须在3个地方修复它。这是一场灾难,也是我最初试图用JPA+注释解决的问题。为什么不仅仅依靠秩序呢?名为“id”的第一列对应于具有“id”字段的第一个实体,下一列对应于下一个实体等。