Reputation: 6989
There is a user entity having one-to-many relationship with role entity. In other words, one user can have multiple roles. Anyhow when I query using JPQL, the Role entity is showing duplicate results, in this case, it shows ROLE_ADMIN
twice. When I debug the code, I can see that the Role entity is having same memory id:
[org.huahsin.Role@1b332d22, org.huahsin.Role@1b332d22]
I wasn't sure whether I have did something wrong in JPQL. Please correct me if I'm wrong. The following are some hints on this problem.
This is the content available in Users table:
+----------+----------+---------+
| username | password | enabled |
+----------+----------+---------+
| user7 | user7 | 1 |
+----------+----------+---------+
This is the table description for Users table:
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | PRI | | |
| password | varchar(32) | YES | | NULL | |
| enabled | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
This is the content available in Authority table:
+----------+------------+
| username | authority |
+----------+------------+
| user7 | ROLE_ADMIN |
| user7 | ROLE_USER |
+----------+------------+
This is the table description for Authority table:
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | MUL | NULL | |
| authority | varchar(10) | NO | | NULL | |
+-----------+-------------+------+-----+---------+-------+
This is the query on User entity:
@NamedQuery(
name="findByUser",
query="select u from User u where u.username in (select r.userId from u.roleList r where r.userId = :username)")
@Entity
@Table(name="users")
public class User {
@Id
private String username;
private String password;
private Integer enabled;
@OneToMany(targetEntity = Role.class, cascade = {CascadeType.ALL})
@JoinColumn(name="username")
private List<Role> roleList;
This is the Role Entity:
@Entity
@Table(name="authority")
public class Role {
@Id
@Column(name="username")
private String userId;
@Column(name="authority")
private String role;
This is how I retrieve the results:
List<User> l = emf.createEntityManager().createNamedQuery("findByUser", User.class).setParameter("username", username).getResultList();
for( User u : l ) {
System.out.println(u.getUsername());
System.out.println(u.getRoleList());
}
Upvotes: 0
Views: 189
Reputation: 242786
It's not clear what you are trying to achieve by this query. If you want to load a user by its username
, and username
is a primary key, you can do it as follows:
User u = em.find(User.class, username);
You get incorrect results because your Role
entity is mapped incorrectly: userId
is annotated as @Id
, but it's not a primary key (i.e. it's not unique).
I'd suggest you to change the database schema. A many-to-many relationship between User
and Role
(with join table) would be much easier to map:
public class User {
...
@OneToMany
@JoinTable(name = "users_authority")
private List<Role> roleList;
...
}
public class Role {
@Id
private String authority;
}
If the current database schema is fixed, you'll need to:
authority
has composite key (username
, authority
) using @EmbeddedId
@MapsId
to indicate the fact that foreign key authority
(username
) is a part of the composite key of authority
See also:
Upvotes: 1