Hi Håkon,
Yes, the latter code you posted (getting the Role entity back from the
DB and then using it for the new User entity) should be the right way
and solve your problem. Please also take care of checking that
CascadeType.ALL, it could delete rows from the Role table even if other
users are actually linked to that Role. CascadeType.PERSIST is safer
when entities in relations are shared (basically, use CascadeType.ALL
with confidence on OneToOne relationship).
You could specify the role column with @Column(unique=true), that is
intended to prevent insertion of more than one line having the same role
value, but actually it would not solve your problem, but only throw an
exception if it detects that you are saving a duplicate row.
The reason why OpenJPA (and any JPA provider) is acting this way is that
you could use the Role class to add more properties to the
User->Roles(enum) relationship. Suppose for example that a user can have
a "state" of his role assignment, something like "requested", "pending
approval", "approved", or a date stating when the user gained that role,
or any other metadata about the using having that role :) . This way,
you can have a user having an approved role of Admin since the 10th
March 2008, another one having the same Admin role since a different
date, and yet another one pending approval for the same Asdmin role
etc..etc.. Obviously in this case, every row in the database must be
unique.
You are using this technique, which is great, but probably a bit
overkill if you only need to map "user A has one or more of this, fixed,
static, roles in an enum, without any other attribute". Unfortunately
however, JPA currently does not support (AFAIK) a way to express a
collection of enum values if not wrapping them in an entity class (which
is what you did), bringing the "metadata" advantage but also the "it's
an entity, so you must fetch it from the database" disadvantage.
Hope this helps,
Simone
Håkon Sagehaug wrote:
hi,
thanks for the replay
see in line
2009/1/16 Simone Gianni <[email protected]>
Hi Håkon,
is the role_id property in the Role entity annotated with @Id or in any
other way considered an ID by OpenJPA?
role_id id annotated with @Id
Are you adding roles to new users creating new instances of the Role
classes (like User u = new User(); u.addRole(new Role(Roles.ADMIN)); .. ) or
getting preexisting Role entities from the database?
yes
If you are creating new Role(..) every time, OpenJPA properly supposes that
is a new row to add to the table.
So I've got get a role from the db and assign this to the users role
Role r1 = roledao.find("Admin")
user.addRole.(r1)
something like this?
Or is it possible to annotate this in a way?
Hope this helps,
Simone
Håkon Sagehaug wrote:
Hi
I've got the following setup. A user entity and a role entity. The user
has
a collection of Role, annotated like this
public class User{
....
@ManyToMany(cascade = CascadeType.ALL)
private Collection<Role> roles = new HashSet<Role>();
}
public Role {
private int role_id;
@Column(name = "role")
private Roles role;
}
Where Roles is a enum, with the possible roles. So first of all is this
the
correct setup if I also want to have many users been able to have the same
role?
e.g User 1, Role:Admin,User,Tester
User2, Role:Admin,Tester
So when persisting a new user the role is also persists the Role object
even
if there is one from before. so in the example above the Admin and tester
role would be inserted twice, and I of course want them to be inserted
just
once. Is there a way to do this? Should annotate the Role entity with
something more?
cheers, Håkon
--
Simone Gianni CEO Semeru s.r.l. Apache Committer
http://www.simonegianni.it/
--
Simone Gianni CEO Semeru s.r.l. Apache Committer
http://www.simonegianni.it/