5 Replies Latest reply on May 28, 2008 11:21 AM by fredf

    collection concurrency problem

    fredf

      I have a unidirectional one-to-many association between an entity 'Media' to an entity 'Comment'.


      My usecase is similar to the commenting in the seam wiki example. The difference is that the relationship between
      Document and Comment in the wiki example is bidirectional.


      My problem is the classic concurreny problem. When two users adds a comment each to a media, User A's comment gets overwritten by User B.
      This is the store comment logic. It like a transaction isolation level problem but on a table level instead of one particular table row.


      @Name("detailedMediaForm")
      @Scope(ScopeType.PAGE)
      public class DetailedMediaForm implements Serializable {
      
           private java.lang.String comment;
      
           private Media media;
      
           private Long mediaId;
           
           private Collection<MediaComment> mediaComments;
      
           // injecting daos
      
           @Create
           public void initMedia() {
                Media loadedMedia = mediaDAO.findById(mediaId);
           }
      
           public String postComment() {
                media = mediaDAO.update(media); // does a merge
                refreshComments();
                MediaComment mediaComment = new MediaComment(comment);
                media.getMediaComments().add(mediaComment);
                messageDAO.create(mediaComment);
                mediaDAO.update(media);
                refreshComments();
                return "success";
           }
      
           public Media getMedia() {
                return media;
           }
      
           public void refreshComments(){
                mediaComments = mediaDAO.findMediaCommentsByMediaId(mediaId);
           }
      
           // plumbing methods
           // getters and setters
      }




      This is the annotation for the comments colleciton in media entity



      @javax.persistence.OneToMany(cascade = {javax.persistence.CascadeType.ALL}, fetch = javax.persistence.FetchType.EAGER)
          @javax.persistence.JoinTable
          (
              name = "MEDIA2MEDIA_COMMENTS",
              joinColumns = {@javax.persistence.JoinColumn(name = "MEDIA_ID_FK", referencedColumnName = "ID")},
              inverseJoinColumns = {@javax.persistence.JoinColumn(name = "MEDIA_COMMENTS_ID_FK", referencedColumnName = "ID")}
          )



      The message is persisted in the MESSAGE table but the rows in the jointable MEDIA2MEDIACOMMENTS between media and comment gets deleted when the link is persisted.
      Why does Hibernate delete the links before inserting the new link to my persisted comment?


      hibernate output


      15:14:55,078 INFO  [STDOUT] Hibernate: /* insert storage.MediaComment */ insert into MESSAGE (ALLOW_COMMENTS, BODY, CONTENT_PROVIDER_ACCOUNT_FK, DATE, TITLE, TYPE) values (?, ?, ?, ?, ?, 'M')
      15:14:55,218 INFO  [STDOUT] Hibernate: /* delete collection convert.frontend.storage.Media.mediaComments */ delete from MEDIA2MEDIA_COMMENTS where MEDIA_ID_FK=?
      15:14:55,218 INFO  [STDOUT] Hibernate: /* insert collection row convert.frontend.storage.Media.mediaComments */ insert into MEDIA2MEDIA_COMMENTS (MEDIA_ID_FK, MEDIA_COMMENTS_ID_FK) values (?, ?)
      15:14:55,218 INFO  [STDOUT] Hibernate: /* insert collection row convert.frontend.storage.Media.mediaComments */ insert into MEDIA2MEDIA_COMMENTS (MEDIA_ID_FK, MEDIA_COMMENTS_ID_FK) values (?, ?)



        • 1. Re: collection concurrency problem
          tom_goring

          Have you looked at @Version to provide optimistic locking?

          • 2. Re: collection concurrency problem
            fredf

            No, but I'll give it a try.

            • 3. Re: collection concurrency problem
              fredf

              I see now what the @Version helps you with. You can spot any concurrency problems by catching OptimisticLockException but as far as I can see, you still have to provide a solution to avoid the lost updates when the exception is caught. Wheather or not I catch the exception I need to build this into my business logic.


              I saw that the way the seam wiki did this was to always merge the document object before writing to it so that it has a fresh comments collection in sync with the persisted ones.


              That is, they always check for the concurrency problem without using @Version mechanism.


              I wonder why my code does not manage to do this? I update my media object (that is eqvivalent to the Document object in the seam wiki example).


              Still my own example differs in behaviour. Anyone got a clue?


              • 4. Re: collection concurrency problem
                christian.bauer

                Fredrik F wrote on May 28, 2008 10:53:


                I saw that the way the seam wiki did this was to always merge the document object before writing to it so that it has a fresh comments collection in sync with the persisted ones.



                This is not correct. The wiki uses a long-running persistence context for these conversations and automatic versioning with @Version. The exception is simply handled in pages.xml with a redirect and a message, no automatic merging or merge screens.


                I recommend that you ask Hibernate questions on the Hibernate forum, I don't see how your problem is related to Seam.

                • 5. Re: collection concurrency problem
                  fredf

                  Thanks for correcting me on this. I should have examined the example more thoroughly. I will continue my thread on the hibernate forum instead (I realized shortly after I posted here that seam forum might not be the right place for this after all :)