2016-10-03 60 views
0

我最近發現了有關審計的envers,並且能夠成功地使用它來跟蹤修訂並使用@Audited註釋和AuditReader來獲取它們。現在,我試圖實現的是在修訂它們而不是最新的修訂版本時保留對被審計實體的映射。使用JPA註釋映射到實體的較早版本

簡單的例子:

比方說,我有我使用,使(僞類下面的類)的餅乾餅乾批次配方。每個配方有一系列指令,跟蹤和這樣做會創建一個批處理:

@Audited 
@Table(name="recipes") 
class CookieRecipe { 
    @OneToMany(mappedBy="recipe") 
    private List<RecipeStep> steps; 

    private void addStep(String instruction) { 
     steps.add(new RecipeStep(instruction)); 
    } 
} 

@Table(name="batches") 
class CookieBatch { 
    @ManyToOne 
    @JoinColumn(...) 
    private CookieRecipe recipe; 
} 

@Audited 
@Table(name="recipe_step") 
class RecipeStep { 

    @Column 
    private String instruction; 

    @ManyToOne 
    @JoinColumn(...) 
    private CookieRecipe recipe; 

    private RecipeStep(String instruction) { 
     this.instruction = instruction; 
    } 
} 

現在,讓我們說我有這樣的餅乾食譜:

CookieRecipe recipe = new CookieRecipe(); 
recipe.addStep("Make the dough"); 
recipe.addStep("Place on pan"); 
recipe.addStep("Bake at 400F for 20 minutes"); 
entityManager.persist(recipe); 

我將使用這個配方打造我的第一批餅乾:

CookieBatch batch = new CookieBatch(recipe); 
entityManager.persist(batch); 

如果我想更改配方的說法,例如,375F,而不是400F,這將創建修訂2 CookieRecipe的,這正是我期待和希望。但是,我希望已創建的批處理指向CookieRecipe的修訂版1。目前,如果我獲取已使用ID創建的CookieBatch,則對CookieRecipe的引用最終將成爲最新版本(375F版本)。

這是我能用envers完成的事情嗎?

+0

'CookieBatch'不是' @審計是故意的?如果是這樣,我不相信有一個優雅的方式來做你想做的事情。 – SergeiBednar

+0

@SergeiBednar是的,唯一的原因是一旦「CookieBatch」完成,它不會改變。所以我認爲這是不必要的,因爲它只會創建一個永遠不會真的被使用的審計表......除非我誤解了這種行爲。如果它導致解決方案,我不反對給它添加'@ Audited'。 – cklab

+0

我認爲你唯一的解決方法就是保留recipeId和recipeRevisionNumber的值,將你的CookieBatch中的recipe配置改爲@vinient,並且通過envers自己處理配方的查詢'AuditCriteria',加載完'CookieBatch'實體後。 – SergeiBednar

回答

2

我相信你這樣做的唯一方法是在你的CookieBatch中保留recipeId,recipeRevisionNumber字段,並自己加載CookieRecipe對象。

@Table(name="batches") 
class CookieBatch { 

    @Column(...) 
    Long recipeId; 

    @Column(...) 
    Long recipeRevisionNumber; 

    @Transient 
    private CookieRecipe recipe; 

    @PostLoad 
    public void loadRecipe() 
    { 
     // Load a cookie recipe via audit criteria 
    } 
} 

審計的標準是不言自明的,看看這個例子:

Hibernate Envers get revisions for criteria

和文檔的所有事情envers:

http://docs.jboss.org/envers/docs/

1

我建議CookieBatch被審計以及保持CookieBatchCookieRecipe之間的雙向關係。這樣,Envers就可以正確地從任何一方查詢適當的版本。

換句話說,添加以下CookieRecipe

@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL) 
private List<CookieRecipeBatch> batches = new ArrayList<>(); 

然後你可以使用下面的循環獲取相應的版本信息的數據:

AuditReader reader = AuditReaderFactory.get(session); 
for (Number revision : reader.getRevisions(CookieRecipe.class, recipeId)) { 
    CookieRecipe recipe = reader.find(CookieRecipe.class, recipeId, revision); 
    // recipe.getSteps() - contains all steps with revision number <= revision 
    // recipe.getBatches() - contains all batches with revision number <= revision 
} 

上面應該給你一個CookieRecipe在特定的使用適當的批處理和步驟快照進行修訂。

+0

我的目標是使用批處理ID獲取一個'CookieBatch',讓它引用'CookieRecipe'的修訂版本在創作時使用。不幸的是,我不知道「適當的修訂」是什麼,那是缺失的數據。除非我特別需要在創建'CookieBatch'時檢索並存儲它,就像@SergeiBednar推薦的那樣? – cklab