无法在envers查询中将关联字段添加到关联字段

时间:2017-07-08 14:59:29

标签: java hibernate spring-data-jpa hibernate-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时,表示关系的字段名称都会出现错误(如果我使用oridinary列,则没有错误。)

我构建了一个审核查询:

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

修改: 我错过了审计查询中的一条陈述。投影应包括parentEntity字段值,而不仅仅是修改标志: 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")));

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

1 个答案:

答案 0 :(得分:1)

如果您真的想在此处使用投影,可以使用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>返回,其中后者返回实际的水合实体实例。