Hi,

I try to update a many to many relationship between a User and Group entity. Lets say the user is member of an additional group.
A simple entityManager.merge(user)
does not work cause in my case the User entity is not the owner-side.
Ok, so i coded this:

EJB method:
// the user entity comes from the GUI so the user and the related
// groups are unmanaged
  public void updateUser(User editedUser)
  {
    User existingUser = entityManager.find(User.class, editedUser.getId());

    List<Group> groupsOfExistingUser = existingUser.getGroups();
    List<Group> groupsOfEditedUser = editedUser.getGroups();

List<Group> addedGroups = determineAddedGroups(groupsOfEditedUser, groupsOfExistingUser); List<Group> removedGroups = determineRemovedGroups(groupsOfEditedUser, groupsOfExistingUser); List<Group> intersectionGroups = determineIntersectionGroups(groupsOfEditedUser, groupsOfExistingUser);

    for (Group group : addedGroups)
    {
      group.getUsers().add(editedUser);
      entityManager.merge(group);
    }

    for (Group group : removedGroups)
    {
      List<User> users = group.getUsers();
      removeUser(users, editedUser.getId());
      entityManager.merge(group);
    }

    for (Group group : intersectionGroups)
    {
      List<User> users = group.getUsers();
      replaceUser(users, editedUser);
      entityManager.merge(group);
    }
    try
    {
      entityManager.flush();
    }
    catch (Exception e)
    {
      e.printStackTrace();
    }
    System.out.println("done");
  }


This looks very complicated to me. Is there an easier way?
Abstract away from the complication this code works only in a junit test
using OpenEJB in local server mode, but in production it does not work, i got the following exception:

<openjpa-1.2.1-r752877:753278 fatal user error> org.apache.openjpa.persistence.InvalidStateException: The generated value processing detected an existing value assigned to this field: de.test.ejb.common.entity.Group.id. This existing value was either provided via an initializer or by calling the setter method. You either need to remove the @GeneratedValue annotation or modify the code to remove the initializer processing. at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:483
)
at org.apache.openjpa.util.ApplicationIds.assign(ApplicationIds.java:463
)
at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.assignObjectId(JDBCSt
oreManager.java:744)
...



@Entity
@Table(name = "USERS")
public class User implements Serializable
{
  private Long id;
  private Long version;
  private String username;
  private List<Group> groups;

  @Id
  @Column(name = "ID")
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  public Long getId()
  {
    return id;
  }

  public void setId(Long id)
  {
    this.id = id;
  }

  @Version
  @Column(name = "OPT_LOCK")
  public Long getVersion()
  {
    return version;
  }

  public void setVersion(Long version)
  {
    this.version = version;
  }

  @Column
  public String getUsername()
  {
    return username;
  }

  public void setUsername(String name)
  {
    this.username = name;
  }

@ManyToMany(mappedBy = "users", fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
  public List<Group> getGroups()
  {
    return groups;
  }

  public void setGroups(List<Group> groups)
  {
    this.groups = groups;
  }
}


@Entity
@Table(name = "GROUPS")
public class Group implements Serializable
{
  private Long id;
  private Long version;
  private String name;
  private List<User> users;

  @Id
  @Column(name = "ID")
  @GeneratedValue(strategy = GenerationType.SEQUENCE)
  public Long getId()
  {
    return id;
  }

  public void setId(Long id)
  {
    this.id = id;
  }

  @Version
  @Column(name = "OPT_LOCK")
  public Long getVersion()
  {
    return version;
  }

  public void setVersion(Long version)
  {
    this.version = version;
  }

  public String getName()
  {
    return name;
  }

  public void setName(String name)
  {
    this.name = name;
  }

@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinTable(name = "GROUPS_USERS", joinColumns = @JoinColumn(name = "GROUP_ID", referencedColumnName = "ID"), inverseJoinColumns = @JoinColumn(name = "USER_ID", referencedColumnName = "ID"))
  public List<User> getUsers()
  {
    return users;
  }

  public void setUsers(List<User> users)
  {
    this.users = users;
  }
}




Reply via email to