3 Replies Latest reply on Aug 3, 2005 6:24 PM by epbernard

    Reassigned existing entities to other entities does not work

    lostinspace2011

      I have the following scenario. A User has several Roles. The relationship between user and role is defined as a bi-directional many-to-many relationship.

      - User A has Role A.

      - To retrieve Roles use :
      User userA = ....
      Roles roles = userA.getRoles()

      - Then I contruct a new user and assign roles to it
      User userB = new User();
      userB.setRoles(userA.getRoles());

      - Then I pass my use to the UserManagerBean to persist it
      UserManager.createNewUser(userB);

      -At this point what I percieve is happening is that all the roles which were previously associated with userA are now reassigned to userB. I have tried retrieving the "new" roles which resulted in :

      User userB = new User();
      userB.setRoles(UserManager.getRoles());

      - In this case the behaviour was correct :-)

      The relationship between user and roles is a ManyToMany relationship without cascading and I am useing JBoss 4.0.3 RC 1 on JDK 1.5.0_04 on Windows XP.

      Any suggestions on this. I believe this to be a bug.

        • 1. Re: Reassigned existing entities to other entities does not
          epbernard

          don't copy the collection instance, add the entities to a new collection isntance.

          • 2. Re: Reassigned existing entities to other entities does not
            lostinspace2011

            Basically the solution is to manually ensure that the relations are within the entity context / session. This is done my attempting a refresh, which might fail with an exception if the bean has not yet been created.

            org.hibernate.UnresolvableObjectException: No row with given identifier exists [ com.j2anywhere.users.Role#0]

            Note that this exception is only throws when an existing Role is associated with the new user. if the role does not exist the framework quite happily persist the user, it's role and the join table via manager.persist(user). Yet if the role already exists a exception is thrown.

            javax.ejb.EJBException: null; CausedByException is:
            detached entity passed to persist: com.j2anywhere.users.Role

            To re-attach the entity to the session we refresh it via manager.refresh(role) and then we are in a position to persist the user.

            It would be nice if the framework could perform this check for us, but at this stage it does not seem to be capable of checking if the contained objects are new or existing one. Also as you have seen from my previous emails doing :

            userB.setRoles(userA.getRoles());


            is a No-No. We will need to copy the individual roles. But this could be done via:
            userB.getRoles().addAll(userA.getRoles());


            Client code:
             User userA = new User();
             userA.setName("User");
             userA.setSurname("A");
             Role roleA = new Role();
             roleA.setName("RoleA");
             userA.getRoles().add(roleA);
             userA = userManager.createUser(userA);
             System.out.println(userA);
            
             User userB = new User();
             userB.setName("User");
             userB.setSurname("A");
             Role foundRole = userManager.findRole("RoleA");
             System.out.println("Found Role : "+foundRole);
             userB.getRoles().add(foundRole);
             userManager.createUser(userB);
             System.out.println(userB);
            

            Within the session bean user :
             public User createUser(User user)
             {
             Iterator>Role< roles = user.getRoles().iterator();
             while (roles.hasNext())
             {
             Role role = roles.next();
             try
             {
             manager.refresh(role);
             }
             catch (org.hibernate.UnresolvableObjectException e)
             {
             System.err.println("Unable to refresh role : "+role);
             manager.persist(role);
             }
             }
             manager.persist(user);
             return user;
             }
            


            Within the entity bean user :
            @ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
             public Collection>Role< getRoles()
             {
             return roles;
             }
             public void setRoles(Collection >Role< roles)
             {
             this.roles = roles;
             }
            


            • 3. Re: Reassigned existing entities to other entities does not
              epbernard

              I don"'t know what you're talking about, just not share collection instances between 2 entities, it's a non sence from a relational perspective.