1 2 Previous Next 19 Replies Latest reply on Jul 31, 2009 7:36 AM by Daniel Hinojosa

    detached entity passed to persist

    Tony Herstell Master

      I have Booking and Users can make a booking.


        

          private User byUser;
      
          @NotNull
          @ManyToOne(cascade={CascadeType.ALL})
          public User getByUser() {
              return byUser;
          }




      Is @ManyToOne correct?



      Assuming it is; when I em.persist(booking); I get 



      19:22:35,657 FATAL [application] javax.ejb.EJBTransactionRolledbackException: org.hibernate.PersistentObjectException: detached entity passed to persist: nz.co.selwynequestriancentre.model.entity.User
      javax.faces.el.EvaluationException: javax.ejb.EJBTransactionRolledbackException: org.hibernate.PersistentObjectException: detached entity passed to persist: nz.co.selwynequestriancentre.model.entity.User




      I tries adding a em.merge(booking.getByUser()); to force the re-attaching of the User to the booking; and Seam goes off and finds it but still dies:



      19:22:35,641 INFO  [STDOUT] Hibernate: select user0_.id as id6_2_, user0_.version4OptLock as version2_6_2_, user0_.password as password6_2_, user0_.email as email6_2_, user0_.avatar_id as avatar23_6_2_, user0_.firstname as firstname6_2_, user0_.surname as surname6_2_, user0_.emailContactOk as emailCon7_6_2_, user0_.homePhone as homePhone6_2_, user0_.mobilePhone as mobilePh9_6_2_, user0_.phoneContactOk as phoneCo10_6_2_, user0_.dressageJudge as dressag11_6_2_, user0_.dressageWriter as dressag12_6_2_, user0_.dressageHelper as dressag13_6_2_, user0_.sjJudge as sjJudge6_2_, user0_.sjHelper as sjHelper6_2_, user0_.showingJudge as showing16_6_2_, user0_.showingHelper as showing17_6_2_, user0_.eventsHelper as eventsH18_6_2_, user0_.termsApproved as termsAp19_6_2_, user0_.creationDate as creatio20_6_2_, user0_.dateEffectiveFrom as dateEff21_6_2_, user0_.dateEffectiveTo as dateEff22_6_2_, roles1_.User_id as User1_4_, selwyneque2_.id as roles2_4_, selwyneque2_.id as id5_0_, selwyneque2_.version4OptLock as version2_5_0_, selwyneque2_.role as role5_0_, image3_.id as id3_1_, image3_.name as name3_1_, image3_.type as type3_1_, image3_.version4OptLock as version4_3_1_, image3_.image as image3_1_ from User user0_ left outer join User_SelwynEquestrianCentreRole roles1_ on user0_.id=roles1_.User_id left outer join SelwynEquestrianCentreRole selwyneque2_ on roles1_.roles_id=selwyneque2_.id left outer join Image image3_ on user0_.avatar_id=image3_.id where user0_.id=?
      19:22:35,657 FATAL [application] javax.ejb.EJBTransactionRolledbackException: org.hibernate.PersistentObjectException: detached entity passed to persist: nz.co.selwynequestriancentre.model.entity.User
      javax.faces.el.EvaluationException: javax.ejb.EJBTransactionRolledbackException: org.hibernate.PersistentObjectException: detached entity passed to persist: nz.co.selwynequestriancentre.model.entity.User



      If I take out the user from booking I can get it to persist (all 4 levels!!!). Has any one got any idea what I am doing wrong?

        • 1. Re: detached entity passed to persist
          Nicklas Karlsson Master

          Hmm, If a user has many bookings I think the normal way would be to map them bidirectionally as


          
            User:
          
            @OneToMany(cascade=ALL, mappedBy="user")
          
            private List<Booking> bookings;
          
          



          
            Booking:
          
            @ManyToOne
          
            private User user;
          
          



          Then just working (merge, persist etc) should work on user...

          • 2. Re: detached entity passed to persist
            Tony Herstell Master

            Nicklas Karlsson wrote on Feb 28, 2008 09:03 AM:


            Hmm, If a user has many bookings I think the normal way would be to map them bidirectionally as

              User:
              @OneToMany(cascade=ALL, mappedBy="user")
              private List<Booking> bookings;
            



              Booking:
              @ManyToOne
              private User user;
            



            Then just working (merge, persist etc) should work on user...



            I couoldnt get the above to work so I pressed on and got the booking persisting (commenting out the User)..


            00:32:55,907 INFO  [STDOUT] Hibernate: insert into Booking (version4OptLock, reason, cost, depositPaid, fullyPaid, eventsManagementSoftwareRequired, title) values (?, ?, ?, ?, ?, ?, ?)
            00:32:55,907 INFO  [STDOUT] Hibernate: insert into BookingDay (version4OptLock, nightBefore, dayNumber, onDate) values (?, ?, ?, ?)
            00:32:55,923 INFO  [STDOUT] Hibernate: insert into Resource (version4OptLock, kind, picture_id) values (?, ?, ?)
            00:32:55,923 INFO  [STDOUT] Hibernate: insert into BookingResource (resource_id, version4OptLock, startHour, startMinute, endHour, endMinute, riders, DTYPE) values (?, ?, ?, ?, ?, ?, ?, 'WithArena')
            00:32:55,923 INFO  [STDOUT] Hibernate: insert into Booking_BookingDay (Booking_id, bookingDays_id) values (?, ?)
            00:32:55,938 INFO  [STDOUT] Hibernate: insert into BookingDay_BookingResource (BookingDay_id, bookingResources_id) values (?, ?)




            This works ok...
            The problem is now that I have altered the User to point back to the 'booking':


            private List<Booking> bookings;
            
                @OneToMany(cascade={CascadeType.ALL})
                 public List<Booking> getBookings() {
                     return bookings;
                }
            
                 public void setBookings(List<Booking> bookings) {
                     this.bookings = bookings;
                }
             



            I cant get the beep thing to persist.




            em.persist(booking);
            
            //User theUser = loggedInUser.getUser();
            //em.merge(theUser);
            //List<Booking> bookings = theUser.getBookings();
            //if (bookings == null) {
            //     bookings = new ArrayList<Booking>();
            //}
            //bookings.add(this.booking);
            //theUser.setBookings(bookings);
            //em.persist(theUser);



            all i ever get is the usual detached entity problem.


            I can't believe this is so hard!

            • 3. Re: detached entity passed to persist
              Tony Herstell Master

                                         


              em.persist(booking);
              User theUser = loggedInUser.getUser();
              em.merge(theUser);
              List<Booking> bookings = theUser.getBookings();
              if (bookings == null) {
                      bookings = new ArrayList<Booking>();
              }
              bookings.add(this.booking);
              theUser.setBookings(bookings);
              //em.merge(theUser);
              em.persist(theUser);




              When I get to the last em.persist I get that the User is detached; but I merged it about 5 lines above.


              Sigh!


              Anyone?

              • 4. Re: detached entity passed to persist
                Nicklas Karlsson Master

                theUser = em.merge(theUser); ?

                • 5. Re: detached entity passed to persist
                  Tony Herstell Master

                  I have no idea why but totally re-reading teh uer from teh database works..
                  Totally inefficient but it works...


                  User theUser = loggedInUser.getUser();
                  User user = (User) em.createQuery("from User u where u.email = :email").setParameter("email", theUser.getEmail()).getSingleResult();
                  List<Booking> bookings = user.getBookings();
                  if (bookings == null) {
                       bookings = new ArrayList<Booking>();
                  }
                  bookings.add(booking);
                  user.setBookings(bookings);
                  em.persist(user);



                  Another part of the project I have no idea why it works; it just does...

                  • 6. Re: detached entity passed to persist
                    Tony Herstell Master

                    01:50:37,313 INFO  [BookingControllerImpl] >setBookingDateRequired Fri Feb 29 00:00:00 NZDT 2008
                    01:50:42,063 INFO  [STDOUT] Hibernate: select user0_.id as id6_, user0_.version4OptLock as version2_6_, user0_.password as password6_, user0_.email as email6_, user0_.avatar_id as avatar23_6_, user0_.firstname as firstname6_, user0_.surname as surname6_, user0_.emailContactOk as emailCon7_6_, user0_.homePhone as homePhone6_, user0_.mobilePhone as mobilePh9_6_, user0_.phoneContactOk as phoneCo10_6_, user0_.dressageJudge as dressag11_6_, user0_.dressageWriter as dressag12_6_, user0_.dressageHelper as dressag13_6_, user0_.sjJudge as sjJudge6_, user0_.sjHelper as sjHelper6_, user0_.showingJudge as showing16_6_, user0_.showingHelper as showing17_6_, user0_.eventsHelper as eventsH18_6_, user0_.termsApproved as termsAp19_6_, user0_.creationDate as creatio20_6_, user0_.dateEffectiveFrom as dateEff21_6_, user0_.dateEffectiveTo as dateEff22_6_ from User user0_ where user0_.email=?
                    01:50:48,782 INFO  [STDOUT] Hibernate: select bookings0_.User_id as User1_1_, bookings0_.bookings_id as bookings2_1_, booking1_.id as id0_0_, booking1_.version4OptLock as version2_0_0_, booking1_.reason as reason0_0_, booking1_.cost as cost0_0_, booking1_.depositPaid as depositP5_0_0_, booking1_.fullyPaid as fullyPaid0_0_, booking1_.eventsManagementSoftwareRequired as eventsMa7_0_0_, booking1_.title as title0_0_ from User_Booking bookings0_ left outer join Booking booking1_ on bookings0_.bookings_id=booking1_.id where bookings0_.User_id=?
                    01:51:02,251 INFO  [STDOUT] Hibernate: select roles0_.User_id as User1_1_, roles0_.roles_id as roles2_1_, selwyneque1_.id as id5_0_, selwyneque1_.version4OptLock as version2_5_0_, selwyneque1_.role as role5_0_ from User_SelwynEquestrianCentreRole roles0_ left outer join SelwynEquestrianCentreRole selwyneque1_ on roles0_.roles_id=selwyneque1_.id where roles0_.User_id=?
                    01:51:02,251 INFO  [STDOUT] Hibernate: insert into Booking (version4OptLock, reason, cost, depositPaid, fullyPaid, eventsManagementSoftwareRequired, title) values (?, ?, ?, ?, ?, ?, ?)
                    01:51:02,266 INFO  [STDOUT] Hibernate: insert into BookingDay (version4OptLock, nightBefore, dayNumber, onDate) values (?, ?, ?, ?)
                    01:51:02,282 INFO  [STDOUT] Hibernate: insert into Resource (version4OptLock, kind, picture_id) values (?, ?, ?)
                    01:51:02,282 INFO  [STDOUT] Hibernate: insert into BookingResource (resource_id, version4OptLock, startHour, startMinute, endHour, endMinute, riders, DTYPE) values (?, ?, ?, ?, ?, ?, ?, 'WithArena')
                    01:51:02,313 INFO  [STDOUT] Hibernate: update User set version4OptLock=?, password=?, email=?, avatar_id=?, firstname=?, surname=?, emailContactOk=?, homePhone=?, mobilePhone=?, phoneContactOk=?, dressageJudge=?, dressageWriter=?, dressageHelper=?, sjJudge=?, sjHelper=?, showingJudge=?, showingHelper=?, eventsHelper=?, termsApproved=?, creationDate=?, dateEffectiveFrom=?, dateEffectiveTo=? where id=? and version4OptLock=?
                    01:51:02,313 INFO  [STDOUT] Hibernate: insert into User_Booking (User_id, bookings_id) values (?, ?)
                    01:51:02,313 INFO  [STDOUT] Hibernate: insert into Booking_BookingDay (Booking_id, bookingDays_id) values (?, ?)
                    01:51:02,329 INFO  [STDOUT] Hibernate: insert into BookingDay_BookingResource (BookingDay_id, bookingResources_id) values (?, ?)
                    01:51:02,470 INFO  [BookingControllerImpl] > destory
                    01:51:02,470 INFO  [BookingControllerImpl] < destory


                    • 7. Re: detached entity passed to persist
                      Vassilis Petropoulos Newbie

                      I had the same problems. The strange thing is that if you ommit entitymanager and use hibernate session (entitymanager.getDelegate) everything works fine.


                      for example:


                      User theUser = loggedInUser.getUser();
                      
                      List<Booking> bookings = user.getBookings();
                      
                      if (bookings == null) {
                      
                           bookings = new ArrayList<Booking>();
                      
                      }
                      
                      bookings.add(booking);
                      
                      user.setBookings(bookings);
                      
                      Session session = (Session) em.getDelegate();
                      
                      session.saveOrUpdate(user);
                      
                      



                      works!


                      V.


                      • 8. Re: detached entity passed to persist
                        Keith Naas Novice

                        In regards to the detached user vs. rereading from the database, rereading is always safe since the entityManager now has a fresh copy in it.  The detached user comes from the fact that the original persistence context has been closed.  Does the loggedInUser object have the the same scope as the component that contains this booking/user code? 



                        FYI: calling setters for managed collections can be dangerous in Hibernate and possibly implementation, you can get a reassociated object has dirty collection reference error message.


                        Instead of calling user.setBookings(bookings), try something like


                        user.getBookings().clear();
                        uer.getBookings().addAll(bookings);
                        



                        You could also initialize bookings in the user object's field declaration for bookings.

                        • 9. Re: detached entity passed to persist
                          Tony Herstell Master

                          Vassilis Petropoulos wrote on Feb 28, 2008 02:14 PM:


                          I had the same problems. The strange thing is that if you ommit entitymanager and use hibernate session (entitymanager.getDelegate) everything works fine.

                          for example:

                          User theUser = loggedInUser.getUser();
                          List<Booking> bookings = user.getBookings();
                          if (bookings == null) {
                               bookings = new ArrayList<Booking>();
                          }
                          bookings.add(booking);
                          user.setBookings(bookings);
                          Session session = (Session) em.getDelegate();
                          session.saveOrUpdate(user);
                          



                          works!

                          V.




                          Doesn't the seam team need to know about this?
                          Isn't it an error and needs a Jira?
                          I have spent Hours on this....

                          • 10. Re: detached entity passed to persist
                            Tony Herstell Master

                            Keith Naas wrote on Feb 28, 2008 03:29 PM:


                            In regards to the detached user vs. rereading from the database, rereading is always safe since the entityManager now has a fresh copy in it.  The detached user comes from the fact that the original persistence context has been closed.  Does the loggedInUser object have the the same scope as the component that contains this booking/user code? 


                            FYI: calling setters for managed collections can be dangerous in Hibernate and possibly implementation, you can get a reassociated object has dirty collection reference error message.

                            Instead of calling user.setBookings(bookings), try something like

                            user.getBookings().clear();
                            uer.getBookings().addAll(bookings);
                            



                            You could also initialize bookings in the user object's field declaration for bookings.


                            I can see that it was safe; but just worried about it being inefficient... I should not have to re-read it from the database once it has been read and is in the session object.


                            loggedInUser it's in the session scope.
                            The booking is conversational.
                            booking reads through a cash of days (next 14 days) to cut down on database traffic and that is Session scoped too.
                            Its all ajaxified using RF which also adds to the complexity.


                            I have added the code changes you suggested about clearing and re-applying the collection - on that I'll take you word for it.

                            • 11. Re: detached entity passed to persist
                              Tony Herstell Master

                              Keith,


                              A number of bookings belong to a user.


                              After fumbling around for a while I settled with this voodoo:


                              Booking     


                              @ManyToOne
                                   public User getUser() {
                                       return user;
                                  }




                              User


                              @OneToMany(cascade={CascadeType.ALL})
                                   public List<Booking> getBookings() {
                                       return bookings;
                                  }




                              This works great in that Seam (Hibernate?) automagically creates a mapping table user_booking that links the two tables together...


                              with or without:


                              user.getBookings().clear();



                              I see in the log that I get


                              12:42:14,657 INFO  [STDOUT] Hibernate: delete from User_Booking where User_id=?



                              Which is bloody odd!!!


                              but with; I DONT get all the existing relationships recreated
                              and without; I DO get all the existing relationships recreated


                              I assume Hibernate has to delete all the old relationships for some internal feature :/


                              SO; basically, without, I get this:


                              12:42:14,657 INFO  [STDOUT] Hibernate: delete from User_Booking where User_id=?
                              12:42:14,657 INFO  [STDOUT] Hibernate: insert into User_Booking (User_id, bookings_id) values (?, ?)
                              12:42:14,657 INFO  [STDOUT] Hibernate: insert into User_Booking (User_id, bookings_id) values (?, ?)
                              12:42:14,657 INFO  [STDOUT] Hibernate: insert into User_Booking (User_id, bookings_id) values (?, ?)
                              12:42:14,657 INFO  [STDOUT] Hibernate: insert into User_Booking (User_id, bookings_id) values (?, ?)




                              Bottom line I can't use the .clear.... should I be worried? or does the above show that Hibernate has put in a workaround for the problem you were alluding to?

                              • 12. Re: detached entity passed to persist
                                Daniel Young Novice

                                No, there is no problem.  Did you try Nicklas' suggestion?


                                theUser = em.merge(theUser);
                                



                                The entity manager javadoc states that merge returns the instance that the state is merged to.  This will be attached to the persistence context and your error should go away.

                                • 13. Re: detached entity passed to persist
                                  Tony Herstell Master

                                  Thanks Daniel,


                                  I did try and still got detached problem.


                                  I went with:


                                  User theUser = loggedInUser.getUser();
                                  User user = (User) em.createQuery("from User u where u.email = :email").setParameter("email", theUser.getEmail()).getSingleResult();
                                  List<Booking> bookings = user.getBookings();
                                  //user.getBookings().clear();
                                  if (bookings == null) {
                                       bookings = new ArrayList<Booking>();
                                  }
                                  bookings.add(booking);
                                  user.setBookings(bookings);
                                  this.booking.setUser(user);
                                  em.persist(user);
                                  



                                  The reason for the //user.getBookings().clear(); is commented above...

                                  • 14. Re: detached entity passed to persist
                                    Daniel Young Novice

                                    That's strange. 


                                    A suggestion on improving your code is you could use em.find() with the User Id instead of having to write a query and set its parameters, etc.  em.find() will also benefit from caching without having to set up specific query caches, etc.

                                    1 2 Previous Next