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;
}
}