2017-07-08 122 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