Best way to merge back an entity retrieved from audit tables ?
toro01 Mar 19, 2012 5:54 AMHi all,
My entities are design like this :
SourceEntity :
@Id() private Long id = null; @Version private long version = 0; @ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, mappedBy = "source", targetEntity = ManyToManyTargetEntity.class) private Set<ManyToManyTargetEntity> manyToMany = new HashSet<ManyToManyTargetEntity>();
ManyToManyTargetEntity :
@Id() private Long id = null; @Version private long version = 0; @ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, mappedBy = "", targetEntity = SourceEntity.class) private Set<SourceEntity> source = new HashSet<SourceEntity>();
Both classes are marked :
@Audited
At t = 1, The initial situation looks like this :
S1, instance of Source entity points to M1 and M2
S2, instance of Source entity points to M1 and M2
M1 instance of ManyToManyTargetEntity points to S1 and S2
M2 instance of ManyToManyTargetEntity points to S1 and S2
At t = 2, I drop M1.
What I am trying to do is to restore the state that was at t = 1 from audited records.
As you can see, I am cascading merge between SourceEntity and ManyToManyTargetEntity, in both directions (bi-directionnal relationship).
I am currently able to retrieve from audited records S1', S2', M1' and M2', which are respectivily the representation of S1, S2, M1 and M2 at t = 1, retrieved from audited records.
A first step to be able to merge everything is to correct the version field in S1', S2', M1' and M2' to match those of S1, S2, M1 and M2, to prevent optimistic lock when applying merge, ie :
entityManager.merge(S1'); entityManager.merge(S2'); entityManager.merge(M1'); entityManager.merge(M2');
I am able to do it so that :
S1'. version == S1.version S2'. version == S2.version M1'. version == M1.version M2'. version == M2.version
However, and this is my problem, when I am merging S1', through cascading, Hibernate is merging the content of :
manyToMany
of S1', and for each object found in it, it tries to merge the content of
source
that leads to an optimistic lock.
From what I can see,S1' does not point to M1', nor M2' (with versions corrected) but to other instances with an incorrect version, hence the optimistic lock.
So many questions...
1) S1', S2', M1' and M2' are retrieved with different queries on the auditReader. Does this explain why S1' does not point to M1' and M2' ? I mean really the same instances ? How to achieve this ?
2) Would you recommend to merge records retrieved from audit tables ? Or is it an intrinsic unsafe operation ? I can also consider a copy method in SourceEntity that would take S1' as parameter and copy S1' content in S1... This would solve merge... but would also cause other problems on relations (how to reassociate ?)
Please tell me if I am unclear.