无法将投影添加到 envers 查询中的关系字段



假设我们有一个实体:

@Entity
@Audited(withModifiedFlag = true)
public class MyEntity  {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false, length = 50)
private String Name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parentEntityId")
private MyEntity parentEntity;
}

我尝试使envers在表示关系的实体字段上返回实体修订信息。我使用addProjection来创建自己的数据表示形式。问题是每次我使用addProjection表示关系的字段名称时,我都会遇到错误(如果我使用原始列,则没有错误(。

我构建了一个审计查询:

AuditQuery auditQuery = reader.createQuery()
.forRevisionsOfEntity(MyEntity.class, false, true);
auditQuery.addProjection(AuditEntity.revisionNumber());
auditQuery.addProjection(AuditEntity.revisionType());        
auditQuery.addProjection(AuditEntity.revisionProperty("timestamp"));
auditQuery.addProjection(AuditEntity.id());
auditQuery.addProjection(new AuditProperty<>(
new EntityPropertyName("parentEntity")));
auditQuery.addProjection(new AuditProperty<>(
new ModifiedFlagPropertyName(
new EntityPropertyName("parentEntity"))));

错误是:

org.hibernate.QueryException: could not resolve property: parentEntity of: edu.sample.domain.entity.MyEntity_AUD

我还尝试:new EntityPropertyName("parentEntityId")- 结果是:

org.hibernate.QueryException: could not resolve property: parentEntityId of: edu.sample.domain.entity.MyEntity_AUD

编辑: 我在审核查询中错过了一个语句。投影应包括父实体字段值,而不仅仅是修改后的标志:auditQuery.addProjection(new AuditProperty<>( new EntityPropertyName("parentEntity")));

我需要字段的值和信息(如果它被修改(。这就是我使用withModifiedFlag = true的原因

问题是MyEntity_AUD表(自动生成(的架构包含字段parentEntityId。修改后的标志字段名称为parentEntity_MOD。错误在添加到查询以下投影后出现:

  • addProjection(new AuditProperty<>( new EntityPropertyName("parentEntity")));

  • addProjection(new AuditProperty<>( new EntityPropertyName("parentEntityId")));

修改标志正确返回,没有错误。以及普通字段的值。

如果您真的想在此处使用投影,您可以使用selectEntity选项执行此操作。 您在此处查找的语法如下:

AuditQuery query = reader.createQuery()
.forRevisionsOfEntity( MyEntity.class, false, true );
query.addProjection( AuditEntity.revisionNumber() );
query.addProjection( AuditEntity.revisionType() );
query.addProjection( AuditEntity.revisionProperty( "timestamp" ) );
query.addProjection( AuditEntity.selectEntity( false ) );

现在,您应该能够使用返回的对象数组中的该特定条目来访问该修订版中的任何关联或属性。 但请注意,这与使用以下语法没有太大区别:

List results = reader.createQuery()
.forRevisionsOfEntity( MyEntity.class, false, true )
.getResultList();
for ( Object row : results ) {
final Object[] array = (Object[]) row;
final MyEntity entity = (MyEntity) array[0];
final Object revisionEntity = array[1];
final RevisionType revisionType = (RevisionType) array[2];
}

这里唯一需要注意的是,revisionEntity可以是 Envers 公开的任意数量的实现,也可以是您自己的自定义实现,具体取决于您配置环境的方式。 您必须检查正在使用哪个并相应地进行转换。

两者是同义词,并产生相同的结果。

唯一真正的区别是,前者将实体作为Map<String,Object>返回,而后者返回实际的水合实体实例。

最新更新