Considering a scenario where I have 2 tables, one table called user, the other table call authority. There is one-to-many relationship, which means each user could have multiple roles. Table below illustrate how this relationship is constructed in database.
Users table
+----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | PRI | | |
| password | varchar(32) | YES | | NULL | |
| enabled | int(11) | YES | | NULL | |
+----------+-------------+------+-----+---------+-------+
Authority table
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| username | varchar(10) | NO | MUL | NULL | |
| authority | varchar(10) | NO | | NULL | |
+-----------+-------------+------+-----+---------+-------+
On Java site, each table is being mapped to the corresponding Java entity as illustrate below:
User entity
@NamedQuery(
name="findByUser",
query="select u from User u join u.roleList r where r.userId = :username ")
@Entity
@Table(name="users")
public class User {
...
@OneToMany(targetEntity = Role.class, cascade = {CascadeType.ALL})
@JoinColumn(name="username")
private List roleList;
...
Role entity
@Entity
@Table(name="authority")
public class Role {
...
With this setup, I don't see any defect in the first run because the test data are a combination of one user pair with one role. The problem comes only when there is one user pair with two roles, I notice that the
roleList will contain duplicate data. To prove my statement, I did some scanning on the data retrieve from the query.
...
User theUser = emf.createEntityManager().createNamedQuery("findByUser", User.class).setParameter("username", username).getSingleResult();
System.out.println(theUser.getRoleList());
...
Code snippet above shows that
theUser.getRoleList() is having duplicate data as it is showing the same memory location
[org.huahsin.Role@1b332d22, org.huahsin.Role@1b332d22] in the console. This problem is due to the Authority table is missing primary key.
Add a primary key into Authority table will fix this problem. A lesson learn, whenever working with JPA, it is best to have the primary key declare in database to allow JPA to have a clear view on the relationship.
No comments:
Post a Comment