【问题标题】:Cannot access JPA joined Entity with HQL无法使用 HQL 访问 JPA 加入的实体
【发布时间】:2017-11-08 14:58:49
【问题描述】:

我有 2 个 ORM 类,一个名为 OpExAlloc,另一个名为 VesselManComp。

第一个与第二个有@ManyToOne 关系,不是在其主键上而是在自定义列上。

这是 OpExAlloc 类中的代码

@Fetch(FetchMode.JOIN)
    @JoinColumns({
            @JoinColumn(name = "companyId", referencedColumnName = "companyId",  insertable = false, updatable = false),
            @JoinColumn(name = "shipCode", referencedColumnName = "code", insertable = false, updatable = false) })
    @ManyToOne(fetch = FetchType.EAGER)
    private VesselManComp vesselManComp;

    public VesselManComp getVesselManComp() {
        return this.vesselManComp;
    }
    public void setVesselManComp(VesselManComp vesselManComp) {
        this.vesselManComp = vesselManComp;
    }

这是 HQL(用于旧版本的 Hibernate 和 XML 配置而不是注释)

    String qs = " select ca.id.docId, ca.id.itemId, ca.id.shipCode, ca.account, "
            + " sum(isnull(ca.quantity, 0)) as quantity, "
            + " sum(isnull(ca.directAmtLocal,0) + isnull(ca.indirectAmtLocal,0) + isnull(ca.nationalTaxLocal,0)) as amountLocal, "
            + " sum(ca.directAmtUsd + ca.indirectAmtUsd + isnull(ca.nationalTaxUsd, 0)) as amountUSD, "
            + " min(ca.id.allocDate) as minDate, "
            + " max(ca.id.allocDate) as maxDate "
            + " from OpExAlloc"
            + " as ca "
            + " where ca.id.companyId = :companyId "
            + " and ca.id.ssId = :sourceSystemId "
            + " and ca.id.type in (:documentTypes) "
            + " and (ca.opexTypeId is null or ca.opexTypeId not in (14, 15)) "
            + " and ca.vesselManComp.code is not null ";

我得到的错误是

java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: code of: com.companyname.orm.sqlserver.aether.dbo.OpExAlloc [ select ca.id.docId, ca.id.itemId, ca.id.shipCode, ca.account,  sum(isnull(ca.quantity, 0)) as quantity,  sum(isnull(ca.directAmtLocal,0) + isnull(ca.indirectAmtLocal,0) + isnull(ca.nationalTaxLocal,0)) as amountLocal,  sum(ca.directAmtUsd + ca.indirectAmtUsd + isnull(ca.nationalTaxUsd, 0)) as amountUSD,  min(ca.id.allocDate) as minDate,  max(ca.id.allocDate) as maxDate  from com.companyname.orm.sqlserver.aether.dbo.OpExAlloc as ca  where ca.id.companyId = :companyId  and ca.id.ssId = :sourceSystemId  and ca.id.type in (:documentTypes)  and (ca.opexTypeId is null or ca.opexTypeId not in (14, 15))  and ca.vesselManComp.code is not null  and ca.id.allocDate >= :allocationDateFrom  and ca.id.allocDate < :allocationDateTo  group by ca.id.docId, ca.id.itemId, ca.id.shipCode, ca.account ]
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:133)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164)

奇怪的事实是 Hibernate 在 OpExAlloc 对象而不是 VesselManComp 对象中寻找“代码”属性。

如果我更改查询以在嵌套对象上添加连接提取

    String qs = " select ca.id.docId, ca.id.itemId, ca.id.shipCode, ca.account, "
            + " sum(isnull(ca.quantity, 0)) as quantity, "
            + " sum(isnull(ca.directAmtLocal,0) + isnull(ca.indirectAmtLocal,0) + isnull(ca.nationalTaxLocal,0)) as amountLocal, "
            + " sum(ca.directAmtUsd + ca.indirectAmtUsd + isnull(ca.nationalTaxUsd, 0)) as amountUSD, "
            + " min(ca.id.allocDate) as minDate, "
            + " max(ca.id.allocDate) as maxDate "
            + " from OpExAlloc"
            + " as ca "
            + " join fetch ca.vesselManComp vmc "
            + " where ca.id.companyId = :companyId "
            + " and ca.id.ssId = :sourceSystemId "
            + " and ca.id.type in (:documentTypes) "
            + " and (ca.opexTypeId is null or ca.opexTypeId not in (14, 15)) "
            + " and vmc.code is not null ";

我得到一个空指针异常

java.lang.NullPointerException
    at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:424)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3921)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3707)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3585)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:720)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:576)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)

有人可以解释我做错了什么吗? 这是我们项目的迁移,旧项目使用 Hibernate 3 和 XML 配置的类,查询工作得很好。

新版本使用带有注释配置的hibernate 5.2。

最好的问候,谢谢, 乔治

【问题讨论】:

  • 你在数据库中的列名也是“code”吗?
  • 数据库中的列名和 VesselManComp 表/orm 实体的属性名都是“代码”全部小写
  • 这可能是愚蠢的评论,因为对 HQL 不太熟悉:在您的 HQL 中是 ca.vesselManComp.code 不是 null 并且在异常中是 vesselManComp.code 是not null ca. 仍引用其他字段。应该这样吗?
  • 我原来的帖子有vesselManComp.code,然后我编辑并添加了ca。前缀并且也没有编辑异常。无论如何,要么与 ca。或不会发生相同的错误。我刚刚编辑了异常以反映代码。

标签: hibernate jpa join entity hql


【解决方案1】:

您的@ManyToOne 注释可能被完全忽略。我注意到注释位于字段上。特定类层次结构(OpExAlloc 类)中使用的访问类型是什么?可以发全班吗?默认情况下,类层次结构的访问类型由 @Id 或 @EmbeddedId 注释的位置定义。如果这些注释在 getter 上,那么 @ManyToOne 注释也应该在 getter 上。有相关帖子 Where to put hibernate annotations?

【讨论】:

  • 感谢您的反馈。你是绝对正确的,当它们被放在属性/字段之上时,注释被完全忽略了,因为 id 注释被放在了 getter 的顶部。现在我需要找出为什么 JOIN 注释是错误的。
猜你喜欢
  • 1970-01-01
  • 2016-02-11
  • 2011-06-24
  • 2015-11-07
  • 2013-01-30
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多