无法使用 HQL 访问 JPA 加入的实体
Cannot access JPA joined Entity with HQL
我有 2 个 ORM classes,一个名为 OpExAlloc,另一个名为 VesselManComp。
第一个与第二个不是在其主键上而是在自定义列上具有@ManyToOne 关系。
这是OpExAlloc中的代码class
@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 对象中查找 "code" 属性。
如果我更改查询以在嵌套对象上添加连接提取
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 配置 classes,查询工作正常。
新的使用 hibernate 5.2 和 classes 的注解配置。
致以诚挚的问候,谢谢,
乔治
您的@ManyToOne 注释可能完全被忽略了。我注意到注释位于字段上。在特定 class 层次结构 (OpExAlloc class) 中使用的访问类型是什么?你能 post 整个 class 吗?默认情况下,class 层次结构的访问类型由 @Id 或 @EmbeddedId 注释的位置定义。如果这些注释在 getter 上,那么 @ManyToOne 注释也应该在 getter 上。有一个相关的 post
Where to put hibernate annotations?
我有 2 个 ORM classes,一个名为 OpExAlloc,另一个名为 VesselManComp。
第一个与第二个不是在其主键上而是在自定义列上具有@ManyToOne 关系。
这是OpExAlloc中的代码class
@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 对象中查找 "code" 属性。
如果我更改查询以在嵌套对象上添加连接提取
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 配置 classes,查询工作正常。
新的使用 hibernate 5.2 和 classes 的注解配置。
致以诚挚的问候,谢谢, 乔治
您的@ManyToOne 注释可能完全被忽略了。我注意到注释位于字段上。在特定 class 层次结构 (OpExAlloc class) 中使用的访问类型是什么?你能 post 整个 class 吗?默认情况下,class 层次结构的访问类型由 @Id 或 @EmbeddedId 注释的位置定义。如果这些注释在 getter 上,那么 @ManyToOne 注释也应该在 getter 上。有一个相关的 post Where to put hibernate annotations?