2016-10-03 146 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