无法解析 Hibernate Envers 复合 Id 实体
Hibernate Envers Composite Id Entity Cannot be Resolved
我有一个复合 ID table,在我的数据库中有一个附加字段,并且使用 EmbeddedId java 持久性注释配置了相应的实体模型。在我的应用程序中执行编辑时,一切正常。但是,当尝试使用 Hibernate Envers 检索审计数据时,代码失败,给我以下堆栈跟踪:
Caused by: org.hibernate.QueryException: could not resolve property: contract_id of: com.mycompany.model.DesignContract_AUD
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:62)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:56)
at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1801)
at org.hibernate.hql.internal.ast.tree.FromElementType.getPropertyType(FromElementType.java:393)
at org.hibernate.hql.internal.ast.tree.FromElement.getPropertyType(FromElement.java:507)
at org.hibernate.hql.internal.ast.tree.DotNode.getDataType(DotNode.java:660)
at org.hibernate.hql.internal.ast.tree.DotNode.prepareLhs(DotNode.java:264)
at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:204)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:109)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:104)
at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1013)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1286)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4699)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4169)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2134)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2059)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2059)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:813)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:607)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:311)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:259)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190)
这里有两个主要问题。首先,Contract_Id 不是字段。我为 JoinColumn 配置了正确的名称 "FK_CONTRACT"。其次,我不明白为什么它试图使用 java class 名称进行审计 table,而不是使用 @Table 注释中设置的名称,这是 "CONTRACT_DESIGNS"。我的class如下:
@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table(name="CONTRACTS")
@Audited
public class Contract implements Serializable {
private static final long serialVersionUID = 1L;
private List<DesignContract> designs;
@OneToMany(mappedBy = "pk.contract", fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
@Fetch(value = FetchMode.SUBSELECT)
public List<DesignContract> getDesigns() {
return designs;
}
public void setDesigns(List<DesignContract> designs) {
this.designs= designs;
}
}
@Entity
@AssociationOverrides({
@AssociationOverride(name = "pk.contract",
joinColumns = @JoinColumn(name = "FK_CONTRACT")),
@AssociationOverride(name = "pk.design",
joinColumns = @JoinColumn(name = "FK_DESIGN")) })
@Table(name="CONTRACT_DESIGNS")
@Audited
public class DesignContract implements Serializable {
private static final long serialVersionUID = 1L;
public DesignContract () {
}
public DesignContract (Contract contract, Design design) {
pk.setContract(contract);
pk.setDesign(design);
}
private DesignContractId pk = new DesignContractId();
@EmbeddedId
public DesignContractId getPk() {
return pk;
}
public void setPk(DesignContractId pk) {
this.pk = pk;
}
@Transient
public Contract getContract() {
return getPk().getContract();
}
public void setContract(Contract contract) {
getPk().setContract(contract);
}
@Transient
public Design getDesign() {
return getPk().getDesign();
}
public void setDesign(Design design) {
getPk().setDesign(design);
}
private Double goal;
@Column(name = "GOAL", nullable = true, insertable = true, updatable = true, precision = 5, scale = 2)
@Basic
public Double getGoal() {
return this.goal;
}
public void setGoal(Double goal) {
this.goal = goal;
}
}
@Embeddable
public class DesignContractId implements Serializable {
private static final long serialVersionUID = 1L;
private Contract contract;
private Design design;
@ManyToOne
public Contract getContract() {
return contract;
}
public void setContract(Contract contract) {
this.contract = contract;
}
@ManyToOne
public Design getDesign() {
return design;
}
public void setDesign(Design design) {
this.design = design;
}
}
所有三个模型都实现了 toString()、hashCode() 和 equals() 方法,为了简洁起见,我只是省略了它们。
我用于检索审计信息的测试代码非常基础,因为我主要只是在做一个概念证明,证明一切正常,并且可以初始化附加到我的主要合同实体的延迟初始化记录。当我调用 DesignContract 列表的 size() 方法时发生错误,根据我发现的其他帖子,这是强制 Hibernate Enver 的 ListProxy intilization 的方法。
AuditReader reader = AuditReaderFactory.get(sessionFactory.openSession());
List<Number> revisionsContract = reader.getRevisions(Contract.class, contractId);
for (Number revisionNum : revisionsContract) {
System.out.println(" revisionNum = " + revisionNum);
Contract contract = reader.find(Contract.class, contractId, revisionNum);
System.out.println(contract.getDesigns().size());
System.out.println(contract.getDesigns());
System.out.println(contract);
}
出于调试目的,我已将 show_sql 设置为 true,调用 size() 时 Hibernate 尝试的查询没有意义:
select e__ from com.mycompany.model.DesignContract_AUD e__ where e__.contract_id = :contract_id and e__.originalId.REVISION_NUMBER.id = (select max(e2__.originalId.REVISION_NUMBER.id) from com.mycompany.model.DesignContract_AUD e2__ where e2__.originalId.REVISION_NUMBER.id <= :revision and e__.originalId.design = e2__.originalId.design and e__.originalId.contract = e2__.originalId.contract) and REVISION_TYPE != :delrevisiontype
同样,没有 contract_id 字段,所以我不知道它是从哪里得到的,因为我在 DesignContract 和 DesignContractId 的模型中给出了注释,我使用 com.mycompany.model.DesignContract_AUD完全听不懂。我什至添加了 @AuditTable 注释,将其指向 CONTRACT_DESIGNS_AUD table,但这并没有改变任何东西。在我的应用程序中执行编辑和保存合同等正常操作时,审计信息被适当地添加到 CONTRACT_DESIGNS_AUD table,我可以直接通过 sql 直接查询信息。我不知道为什么 AuditReader 会发生这种情况。我的应用程序中有多个复合 ID 实体,它们都以相同的方式配置,并且都遇到相同的错误,具有未知的 contract_id 参数和 java class查询中用于审核 table 的名称。我确实尝试将我的模型配置为使用 @IdClass 注释而不是 @EmbeddedId,但这仅有助于解析查询中的 table 名称 - 它仍然尝试基于 contract_id 进行过滤,当然,它指出无法解决。
我正在使用 Hibernate 5.2。10.FINAL,我在阅读复合 Id 实体无法与早期版本的 Hibernate Envers 一起使用后升级到它 - https://hibernate.atlassian.net/browse/HHH-7625
对于我做错了什么的任何帮助将不胜感激。
我有一个复合 ID table,在我的数据库中有一个附加字段,并且使用 EmbeddedId java 持久性注释配置了相应的实体模型。在我的应用程序中执行编辑时,一切正常。但是,当尝试使用 Hibernate Envers 检索审计数据时,代码失败,给我以下堆栈跟踪:
Caused by: org.hibernate.QueryException: could not resolve property: contract_id of: com.mycompany.model.DesignContract_AUD
at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:62)
at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:56)
at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1801)
at org.hibernate.hql.internal.ast.tree.FromElementType.getPropertyType(FromElementType.java:393)
at org.hibernate.hql.internal.ast.tree.FromElement.getPropertyType(FromElement.java:507)
at org.hibernate.hql.internal.ast.tree.DotNode.getDataType(DotNode.java:660)
at org.hibernate.hql.internal.ast.tree.DotNode.prepareLhs(DotNode.java:264)
at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:204)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:109)
at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:104)
at org.hibernate.hql.internal.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:1013)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1286)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4699)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:4169)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2134)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2059)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2059)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.whereClause(HqlSqlBaseWalker.java:813)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:607)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:311)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:259)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190)
这里有两个主要问题。首先,Contract_Id 不是字段。我为 JoinColumn 配置了正确的名称 "FK_CONTRACT"。其次,我不明白为什么它试图使用 java class 名称进行审计 table,而不是使用 @Table 注释中设置的名称,这是 "CONTRACT_DESIGNS"。我的class如下:
@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table(name="CONTRACTS")
@Audited
public class Contract implements Serializable {
private static final long serialVersionUID = 1L;
private List<DesignContract> designs;
@OneToMany(mappedBy = "pk.contract", fetch = FetchType.EAGER, cascade = {CascadeType.ALL}, orphanRemoval=true)
@Fetch(value = FetchMode.SUBSELECT)
public List<DesignContract> getDesigns() {
return designs;
}
public void setDesigns(List<DesignContract> designs) {
this.designs= designs;
}
}
@Entity
@AssociationOverrides({
@AssociationOverride(name = "pk.contract",
joinColumns = @JoinColumn(name = "FK_CONTRACT")),
@AssociationOverride(name = "pk.design",
joinColumns = @JoinColumn(name = "FK_DESIGN")) })
@Table(name="CONTRACT_DESIGNS")
@Audited
public class DesignContract implements Serializable {
private static final long serialVersionUID = 1L;
public DesignContract () {
}
public DesignContract (Contract contract, Design design) {
pk.setContract(contract);
pk.setDesign(design);
}
private DesignContractId pk = new DesignContractId();
@EmbeddedId
public DesignContractId getPk() {
return pk;
}
public void setPk(DesignContractId pk) {
this.pk = pk;
}
@Transient
public Contract getContract() {
return getPk().getContract();
}
public void setContract(Contract contract) {
getPk().setContract(contract);
}
@Transient
public Design getDesign() {
return getPk().getDesign();
}
public void setDesign(Design design) {
getPk().setDesign(design);
}
private Double goal;
@Column(name = "GOAL", nullable = true, insertable = true, updatable = true, precision = 5, scale = 2)
@Basic
public Double getGoal() {
return this.goal;
}
public void setGoal(Double goal) {
this.goal = goal;
}
}
@Embeddable
public class DesignContractId implements Serializable {
private static final long serialVersionUID = 1L;
private Contract contract;
private Design design;
@ManyToOne
public Contract getContract() {
return contract;
}
public void setContract(Contract contract) {
this.contract = contract;
}
@ManyToOne
public Design getDesign() {
return design;
}
public void setDesign(Design design) {
this.design = design;
}
}
所有三个模型都实现了 toString()、hashCode() 和 equals() 方法,为了简洁起见,我只是省略了它们。
我用于检索审计信息的测试代码非常基础,因为我主要只是在做一个概念证明,证明一切正常,并且可以初始化附加到我的主要合同实体的延迟初始化记录。当我调用 DesignContract 列表的 size() 方法时发生错误,根据我发现的其他帖子,这是强制 Hibernate Enver 的 ListProxy intilization 的方法。
AuditReader reader = AuditReaderFactory.get(sessionFactory.openSession());
List<Number> revisionsContract = reader.getRevisions(Contract.class, contractId);
for (Number revisionNum : revisionsContract) {
System.out.println(" revisionNum = " + revisionNum);
Contract contract = reader.find(Contract.class, contractId, revisionNum);
System.out.println(contract.getDesigns().size());
System.out.println(contract.getDesigns());
System.out.println(contract);
}
出于调试目的,我已将 show_sql 设置为 true,调用 size() 时 Hibernate 尝试的查询没有意义:
select e__ from com.mycompany.model.DesignContract_AUD e__ where e__.contract_id = :contract_id and e__.originalId.REVISION_NUMBER.id = (select max(e2__.originalId.REVISION_NUMBER.id) from com.mycompany.model.DesignContract_AUD e2__ where e2__.originalId.REVISION_NUMBER.id <= :revision and e__.originalId.design = e2__.originalId.design and e__.originalId.contract = e2__.originalId.contract) and REVISION_TYPE != :delrevisiontype
同样,没有 contract_id 字段,所以我不知道它是从哪里得到的,因为我在 DesignContract 和 DesignContractId 的模型中给出了注释,我使用 com.mycompany.model.DesignContract_AUD完全听不懂。我什至添加了 @AuditTable 注释,将其指向 CONTRACT_DESIGNS_AUD table,但这并没有改变任何东西。在我的应用程序中执行编辑和保存合同等正常操作时,审计信息被适当地添加到 CONTRACT_DESIGNS_AUD table,我可以直接通过 sql 直接查询信息。我不知道为什么 AuditReader 会发生这种情况。我的应用程序中有多个复合 ID 实体,它们都以相同的方式配置,并且都遇到相同的错误,具有未知的 contract_id 参数和 java class查询中用于审核 table 的名称。我确实尝试将我的模型配置为使用 @IdClass 注释而不是 @EmbeddedId,但这仅有助于解析查询中的 table 名称 - 它仍然尝试基于 contract_id 进行过滤,当然,它指出无法解决。
我正在使用 Hibernate 5.2。10.FINAL,我在阅读复合 Id 实体无法与早期版本的 Hibernate Envers 一起使用后升级到它 - https://hibernate.atlassian.net/browse/HHH-7625
对于我做错了什么的任何帮助将不胜感激。