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/

Reply via email to