5 Replies Latest reply on Mar 26, 2012 11:16 AM by adamw

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

    toro01

      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.