1 Reply Latest reply on Dec 12, 2008 3:10 PM by Agnieszka Kozak

    Troubles With Many-to-Many

    Josh Martin Newbie

      Hey guys,


      Im using JBoss AS 4.3.2 GA, Seam 2.0.2.SP1, and MySQL.


      Ive got two entities with a many to many relation between them.  When I try to update the relational table, the changes dont persist.  Also, when I edit one of the entities, all the corresponding entries in the relational table get aced.  I have a hack/work around for that but I would much rather do it the right way.  Here is my code:


      User entity:


      package com.burris.essapp.model;
      
      // imports
      
      @Entity
      @Name( "user" )
      public class User implements Serializable {
      
              private String userId;
              private String password;
              private String firstName;
              private String lastName;
              private String email;
              private long phone;
      
              private List<Role> roles;
      
              private List<Role> unassignedRoles;
              
              public User() {
      
                      super();
              }
      
              public User( String userId, String password ) {
      
                      super();
                      this.userId = userId;
                      this.password = password;
              }
      
              public User( String userId, String password, String firstName, String lastName ) {
      
                      super();
                      this.userId = userId;
                      this.password = password;
                      this.firstName = firstName;
                      this.lastName = lastName;
              }
      
              public User( String userId, String password, String firstName, String lastName, String email, long phone ) {
      
                      super();
                      this.userId = userId;
                      this.password = password;
                      this.firstName = firstName;
                      this.lastName = lastName;
                      this.email = email;
                      this.phone = phone;
              }
      
              @Id
              public String getUserId() {
      
                      return userId;
              }
      
              public void setUserId( String userId ) {
      
                      this.userId = userId;
              }
      
              public String getPassword() {
      
                      return password;
              }
      
              public void setPassword( String password ) {
      
                      this.password = password;
              }
      
              public String getFirstName() {
      
                      return firstName;
              }
      
              public void setFirstName( String firstName ) {
      
                      this.firstName = firstName;
              }
      
              public String getLastName() {
      
                      return lastName;
              }
      
              public void setLastName( String lastName ) {
      
                      this.lastName = lastName;
              }
      
              public String getEmail() {
      
                      return email;
              }
      
              public void setEmail( String email ) {
      
                      this.email = email;
              }
      
              public Long getPhone() {
      
                      return phone;
              }
      
              public void setPhone( Long phone ) {
      
                      this.phone = phone;
              }
      
              @ManyToMany( fetch = FetchType.EAGER )
              @JoinTable( name = "UserRole", joinColumns = { @JoinColumn( name = "userId" ) }, inverseJoinColumns = { @JoinColumn( name = "roleId" ) } )
              public List<Role> getRoles() {
      
                      if (roles == null) {
      
                              roles = new ArrayList<Role>();
                      }
      
                      return this.roles;
              }
      
              public void setRoles( List<Role> roles ) {
      
                      this.roles = roles;
              }
              
              @Transient
              public List<Role> getUnassignedRoles() {
              
                      return unassignedRoles;
              }
      
              
              public void setUnassignedRoles( List<Role> unassignedRoles ) {
              
                      this.unassignedRoles = unassignedRoles;
              }
      
              @Override
              public int hashCode() {
      
                      final int prime = 31;
                      int result = 1;
                      result = prime * result + ((email == null) ? 0 : email.hashCode());
                      result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
                      result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
                      result = prime * result + ((password == null) ? 0 : password.hashCode());
                      result = prime * result + (int) (phone ^ (phone >>> 32));
                      result = prime * result + ((userId == null) ? 0 : userId.hashCode());
                      return result;
              }
      
              @Override
              public boolean equals( Object obj ) {
      
                      if (this == obj)
                              return true;
                      if (obj == null)
                              return false;
                      if (getClass() != obj.getClass())
                              return false;
                      final User other = (User) obj;
                      if (email == null) {
                              if (other.email != null)
                                      return false;
                      }
                      else if (!email.equals( other.email ))
                              return false;
                      if (firstName == null) {
                              if (other.firstName != null)
                                      return false;
                      }
                      else if (!firstName.equals( other.firstName ))
                              return false;
                      if (lastName == null) {
                              if (other.lastName != null)
                                      return false;
                      }
                      else if (!lastName.equals( other.lastName ))
                              return false;
                      if (password == null) {
                              if (other.password != null)
                                      return false;
                      }
                      else if (!password.equals( other.password ))
                              return false;
                      if (phone != other.phone)
                              return false;
                      if (userId == null) {
                              if (other.userId != null)
                                      return false;
                      }
                      else if (!userId.equals( other.userId ))
                              return false;
                      return true;
              }
      
              @Override
              public String toString() {
      
                      return this.userId;
              }




      UserManagerBean:


      package com.burris.essapp.action;
      
      // imports
      
      @Stateful
      @Name( "usermanager" )
      @Scope( CONVERSATION )
      public class UserManagerBean implements UserManager {
      
              @In( create = true )
              @Out
              private User user;
      
              @Out
              private List<User> users;
      
              @PersistenceContext
              private EntityManager em;
      
              @Factory( "users" )
              public void getAll() {
      
                      this.users = em.createQuery( "select u from User u" ).getResultList();
              }
      
              @Begin
              public String beginCreate() {
                      
                      return null;
              }
      
              @End
              public String endCreate() {
      
                      Role employee = em.find( Role.class, "employee" );
                      this.user.getRoles().add( employee );
                      
                      this.em.persist( user );
                      this.user = new User();
                      this.users = em.createQuery( "select u from User u" ).getResultList();
      
                      return null;
              }
      
              @Begin
              public String beginEdit( Object user ) {
      
                      if (user instanceof User) {
                              
                              this.user = (User) user;
                      }
                      else {
                              
                              throw new ClassCastException( "Expected a User object." );
                      }
                      
                      return null;
              }
      
              @End
              public String endEdit() {
      
                      User tempUser = this.em.find( User.class, this.user.getUserId() );
                      this.user.setRoles( tempUser.getRoles() );
                      this.em.merge( user );
                      |this.users = em.createQuery( "select u from User u" ).getResultList();
      
                      return null;
              }
              
              @Begin
              public String beginRoleEdit( User user ) {
      
                      if (user instanceof User) {
                              
                              this.user = (User) user;
                              
                              List<Role> unassignedRoles = em.createQuery( "select r from Role r" ).getResultList();
                              unassignedRoles.removeAll( this.user.getRoles() );
                              
                              this.user.setUnassignedRoles( unassignedRoles );
                      }
                      else {
                              
                              throw new ClassCastException( "Expected a User object." );
                      }
                      
                      return null;
              }
              
              @End
              public String endRoleEdit() {
      
                      User tempUser = this.em.find( User.class, this.user.getUserId() );
                      tempUser.setRoles( this.user.getRoles() );
                      this.em.merge( tempUser );
                      this.user = new User();
      //              this.users = em.createQuery( "select u from User u" ).getResultList();
      
                      return null;
              }
      
              @Begin
              public String beginDelete( Object user ) {
      
                      if (user instanceof User) {
                              
                              this.user = (User) user;
                      }
                      else {
                              
                              throw new ClassCastException( "Expected a User object." );
                      }
                      
                      return null;
              }
      
              @End
              public String endDelete() {
      
                      User tempUser = em.merge( user );
                      this.em.remove( tempUser );
                      this.users = em.createQuery( "select u from User u" ).getResultList();
      
                      this.user = new User();
      
                      return null;
              }
      
              @End
              public String cancel() {
      
                      this.users = em.createQuery( "select u from User u" ).getResultList();
                      this.user = new User();
      
                      return null;
              }
      
              @Destroy
              @Remove
              public void destroy() {
      
              }
      
              public User getUser() {
      
                      return user;
              }
      
              public void setUser( User user ) {
      
                      this.user = user;
              }
      
              public List<User> getUsers() {
      
                      return users;
              }
      
              public void setUsers( List<User> users ) {
      
                      this.users = users;
              }
      }





      console.xhtml:


                     <rich:tab label="User Manager">
                              <ui:include src="userModalPanels.xhtml"></ui:include>
                              
                              <h:commandButton id="openCreateUserPanel" value="Add User" action="#{usermanager.beginCreate}">
                                      <rich:componentControl for="createUserPanel" attachTo="openCreateUserPanel" operation="show" event="onclick"/>
                              </h:commandButton>
                              
                              <h:form>
                                      <rich:dataTable id="usersTable" value="#{users}" var="u" rows="10">
                                              <f:facet name="header">
                                      <rich:datascroller id="userTableScroller1" for="usersTable" ajaxSingle="false" reRender="userTableScroller2" />
                                      </f:facet>
                                      
                                              <rich:column>
                                                      <f:facet name="header"><h:outputText value="User ID" /></f:facet>
                                                      <h:outputText value="#{u.userId}" />
                                              </rich:column>
                                              
                                              <rich:column>
                                                      <f:facet name="header"><h:outputText value="Last Name" /></f:facet>
                                                      <h:outputText value="#{u.lastName}" />
                                              </rich:column>
                                              
                                              <rich:column>
                                                      <f:facet name="header"><h:outputText value="First Name" /></f:facet>
                                                      <h:outputText value="#{u.firstName}" />
                                              </rich:column>
                                              
                                              <rich:column>
                                                      <f:facet name="header"><h:outputText value="Phone" /></f:facet>
                                                      <h:outputText value="#{u.phone}" />
                                              </rich:column>
                                              
                                              <rich:column>
                                                      <f:facet name="header"><h:outputText value="Email" /></f:facet>
                                                      <h:outputText value="#{u.email}" />
                                              </rich:column>
                                              
                                              <rich:column>
                                                      <f:facet name="header"><h:outputText value="Actions" /></f:facet>
                                                      
                                                      <a4j:commandButton value="Edit" action="#{usermanager.beginEdit(u)}" oncomplete="Richfaces.showModalPanel('editUserPanel');" reRender="userInfoToEdit" />
                                                      <a4j:commandButton value="Roles" action="#{usermanager.beginRoleEdit(u)}" oncomplete="Richfaces.showModalPanel('editRolesUserPanel');" reRender="userRolesToEdit" />
                                                      <a4j:commandButton value="Delete" action="#{usermanager.beginDelete(u)}" oncomplete="Richfaces.showModalPanel('deleteUserPanel');" reRender="userInfoToDelete" />
                                              </rich:column>
                                              
                                              <f:facet name="footer">
                                      <rich:datascroller id="userTableScroller2" for="usersTable" ajaxSingle="false" reRender="userTableScroller1" />
                                      </f:facet>
                                      </rich:dataTable>
                              </h:form>
                      </rich:tab>|
      
      Modal Panels:
      |       <rich:modalPanel id="editUserPanel" width="300" height="100">
                      <f:facet name="header">
                              <h:outputText value="Edit User Information" />
                      </f:facet>
              
              <h:outputText value="Fields marked with an * are required." />
              <s:div id="userInfoToEdit">
                              <h:form>
                                      <rich:spacer height="15" />
                      
                                      <h:panelGrid columns="2">
                                          <h:outputText value="Editing: " />
                                              <h:outputText value="#{user.userId}" />
                                              
                                              <rich:spacer height="15" />
                                              <rich:spacer height="15" />
                                              
                                              <h:outputText for="password" value="*Password:" />
                                              <h:inputSecret id="password" value="#{user.password}" redisplay="true" />
                                                              
                                              <h:outputText for="lastName" value="Last Name:" />
                                              <h:inputText id="lastName" value="#{user.lastName}" />
                                                                                              
                                              <h:outputText for="firstName" value="First Name:" />
                                              <h:inputText id="firstName" value="#{user.firstName}" />
                                                                                              
                                              <h:outputText for="phone" value="Phone:" />
                                              <h:inputText id="phone" value="#{user.phone}" />
                                                              
                                              <h:outputText for="email" value="Email:" />
                                              <h:inputText id="email" value="#{user.email}" />
                                              
                                              <h:outputText for="userId" value="" />
                                              <h:inputHidden id="userId" value="#{user.userId}" />
                                      </h:panelGrid>
                                      
                                      <rich:spacer height="15" />
                                      
                                      <center>
                                              <h:commandButton value="Save" action="#{usermanager.endEdit}" oncomplete="Richfaces.hideModalPanel('editUserPanel'); return false" />
                                      <h:commandButton value="Cancel" action="#{usermanager.cancel}" oncomplete="Richfaces.hideModalPanel('editUserPanel'); return false" />
                              </center>
                              </h:form>
                      </s:div>
              </rich:modalPanel>
              
              <rich:modalPanel id="editRolesUserPanel" width="300" height="100">
                      <f:facet name="header">
                              <h:outputText value="Edit User Roles" />
                      </f:facet>
              
              <s:div id="userRolesToEdit">
                      <h:outputText for="userId" value="Editing: " />
                              <h:outputText id="userId" value="#{user.userId}" />
                              
                              <rich:spacer height="15" />
                              
                      <rich:listShuttle id="userShuttle" sourceValue="#{user.unassignedRoles}" targetValue="#{user.roles}" var="r" converter="org.jboss.seam.ui.EntityConverter" fastOrderControlsVisible="false" orderControlsVisible="false">
                                      <h:column>
                                              <h:outputText value="#{r.roleId}" />
                                      </h:column>
                                      
                                      <a4j:support event="onlistchanged" reRender="userRolesToEdit" />
                              </rich:listShuttle>
                      </s:div>
                      
                      <rich:spacer height="15" />
                      
                      <center>
                              <s:button value="Save" action="#{usermanager.endRoleEdit}" onclick="Richfaces.hideModalPanel('editRolesUserPanel'); return false" />
                              <s:button value="Cancel" action="#{usermanager.cancel}" onclick="Richfaces.hideModalPanel('editRolesUserPanel'); return false" />
                      </center>
              </rich:modalPanel>





      Ive looked over this for a while and I cant find my error and it is getting frustrating.