2017-07-08 62 views
0

让我们说我们有一个实体:无法addProjection到关系领域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 

编辑 : 我错过了Audit que中的一条语句RY。该投影应该包含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")));

的修改标志被正确无误返回。以及普通领域的价值。

+0

当指定'selectOnlyEntities = false'时,为什么需要使用投影而不是使用返回的Object []',是否有一个特定的原因? – Naros

回答

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>,因为后者返回实际水合实体实例。

+0

我在[envers docs](http://docs.jboss.org/envers/api-new/org/hibernate/envers/query/AuditEntity.html)找不到'AuditEntity.selectEntity'方法。 addProjection用法的根源在于需要获取有关字段修改的信息(我使用'withModifiedFlag = true')。我可以通过其他方式获得这些信息吗?没有'addProjection'? – piradian

+0

Mayby我应该创建:'@Entity class MyEntity_AUD {...}'? – piradian

+0

如果你没有使用Hibernate 5.2.x,你将看不到该方法。它被添加为Envers的新的关联遍历支持的一部分。否则,你将不得不诉诸我发布的早期版本的后一个解决方案。至于创建实体,不要这样做。如果你碰到类似的名字,你会打破与Envers的整合。 – Naros