【问题标题】:Unable to addProjection to relation field in envers query无法将投影添加到 envers 查询中的关系字段
【发布时间】:2017-07-08 14:59:29
【问题描述】:

假设我们有一个实体:

@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

编辑: 我错过了审计查询中的一条语句。投影应包括 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")));

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

【问题讨论】:

  • 在指定selectOnlyEntities=false 时,是否有特定原因需要使用投影而不是使用返回的Object[]

标签: java hibernate spring-data-jpa hibernate-envers


【解决方案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&lt;String,Object&gt; 返回,而后者则返回实际的水合实体实例。

【讨论】:

  • 我在envers docs 中找不到AuditEntity.selectEntity 方法。 addProjection 用法的根源在于需要获取有关字段修改的信息(我使用 withModifiedFlag=true)。如果没有addProjection,我可以通过其他方式获取此信息吗?
  • 也许我应该创建:@Entity class MyEntity_AUD{ ...} ?
  • 如果您没有使用 Hibernate 5.2.x,您将看不到该方法。它是作为对 Envers 的新关联遍历支持的一部分而添加的。否则,您将不得不求助于我为早期版本发布的后一种解决方案。至于创建实体,请不要这样做。如果您像这样冲突名称,您将破坏与 Envers 的集成。
  • 但是我怎样才能获得关于 vaule 的信息以及修改标志?直到关系表示字段的问题,我已经完成了投影auditQuery.addProjection(new AuditProperty&lt;&gt;( new EntityPropertyName("name")));auditQuery.addProjection(new AuditProperty&lt;&gt;( new ModifiedFlagPropertyName( new EntityPropertyName("name"))));。这很好。问题在于关系。我无法在这样的领域进行投影。
  • 这是因为关系支持作为查询 API 本身的一部分是相对较新的东西,并且仍在添加/调整中。正如我已经提到的,如果您想使用投影 API,则需要升级到 5.2+,或者如果您想继续使用 5.2 的先前版本,则使用提到的后一种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多