使用JPA注释映射到较旧版本的实体

时间:2016-10-03 21:47:45

标签: hibernate jpa hibernate-envers

我最近发现了有关审核的内容,并且能够成功使用它来跟踪修订并使用@Audited注释和AuditReader来获取它们。现在,我试图实现的目标是在审核实体的修订版本中保留映射,而不是最新版本。

快速举例:

让我们说我有一个cookie的配方,我用它来制作批量的cookie(下面的类的伪类)。每个配方都有一个要遵循的说明列表,这样做会创建批次:

@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;
    }
}

现在,让我们说我有这个Cookie食谱:

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);

我将使用此配方创建我的第一批Cookie:

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

如果我想更改配方,例如375F而不是400F,则会创建CookieRecipe的修订版2,这是我期望和想要的。但是,我希望我已经创建的批处理指向CookieRecipe的修订版1。目前,如果我使用其ID获取已创建的CookieBatch,则CookieRecipe的引用最终将成为最新版本(375F的版本)。

这是我可以使用envers完成的事情吗?

2 个答案:

答案 0 :(得分:2)

我相信您这样做的唯一方法是在recipeId中保留recipeRevisionNumberCookieBatch个字段,并自行加载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

以及所有内容的文档:

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

答案 1 :(得分: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