2016-10-03 8 views
0

Недавно я узнал об объявлении для аудита и смог успешно использовать его для отслеживания изменений и получения их с помощью аннотации @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, который является то, что я ожидал и хочу. Однако я хочу, чтобы пакет, который я уже создал, указывал на ревизию 1 CookieRecipe. В настоящее время, если я получаю CookieBatch, я уже создал его идентификатор, ссылка на CookieRecipe заканчивается последней версией (с 375F).

Это что-то, что я могу выполнить с помощью envers?

+0

'CookieBatch' не является' @ Audited' намеренно? Если это так, я не думаю, что есть элегантный способ сделать то, что вы пытаетесь сделать. – SergeiBednar

+0

@SergeiBednar Да, только причина заключается в том, что после завершения «CookieBatch» он не изменяется.Поэтому я подумал, что это необязательно, так как это просто создаст таблицу аудита, которая никогда не будет использоваться ... если я не понял это поведение. Я не против добавления в него '@ Audited', если это приведет к решению. – cklab

+0

Я думаю, что ваше единственное другое решение здесь - сохранить значения 'recipeId' и' recipeRevisionNumber', изменить сущность 'recipe' в вашей' CookieBatch' на '@ Transient' и обрабатывать запрос рецепта самостоятельно, через envers 'AuditCriteria', после загрузки объекта' CookieBatch'. – SergeiBednar

ответ

2

Я считаю, что ваш единственный способ сделать это: сохранить recipeId, recipeRevisionNumber полей в вашем CookieBatch и загрузить объект 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, а также поддерживать двунаправленную связь между CookieBatch и CookieRecipe. Таким образом, 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

Моя цель - получить «CookieBatch» с использованием идентификатора пакета и обратиться к редакции 'CookieRecipe' используемый во время создания. К сожалению, я не знаю, что такое «соответствующая ревизия», это недостающие данные. Если я специально не должен извлекать и хранить это при создании 'CookieBatch', как то, что рекомендует @SergeiBednar? – cklab

Смежные вопросы