5 Replies Latest reply: Mar 26, 2012 11:16 AM by Adam Warski RSS

Best way to merge back an entity retrieved from audit tables ?

Benoit Cantin Newbie

Hi 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.