列出类的所有实体时,JPA返回同一实例的多个对象

时间:2012-08-09 15:01:40

标签: jpa persistence db2

我有一个JPA实体,其中包含子实体列表。在这种情况下,附加了角色的用户实体。

它看起来(有点简化 - 省略了一些字段/方法),如下所示:

@Entity
public class MyUser{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long myUserId;

 private String username; 

 @OneToMany
 @JoinTable(name = "userrole",
   joinColumns = {
     @JoinColumn(name="myUserId", unique = true)           
   },
   inverseJoinColumns = {
     @JoinColumn(name="roleId")
   }
 )
 private Collection<Role> roles;    

 public Collection<Role> getRoles() {
     return roles;
 }
}

如果是intressting,则Role实体非常简单。

@Entity
public class Role {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long roleId;
  private String role; // a few more string fields here .

当我为每个用户添加两个用户和几百个角色时,当我列出用户时,我会得到一个奇怪的行为。每个用户被列出几百次(相同的用户=相同的唯一ID)。

有问题的代码:

Query q = em.createQuery("SELECT u FROM MyUser u LEFT JOIN FETCH u.roles");
Collection<MyUser> users = q.getResultList();

for(MyUser u : users){
     // print/use u here
} 

然而,当我只是访问数据库并执行select语句时,似乎没问题。每个用户只存在一次。

在这种情况下,我将OpenJPA 1.2与IBM DB2数据库一起使用。

2 个答案:

答案 0 :(得分:1)

我认为你的模型有问题,通常用户角色关系不是OneToMany而是“ManyToMany”所以你应该改变你的代码看起来像这样:

@Entity
public class MyUser{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Long myUserId;

 private String username; 

 @ManyToMany //This should be many to many
 @JoinTable(name = "userrole",
   joinColumns = {
     @JoinColumn(name="myUserId") //The userId in the join table should
                                  //NOT be unique because the userId can
                                  //be many times with different roles
   },
   inverseJoinColumns = {
     @JoinColumn(name="roleId")
   }
 )
 private Collection<Role> roles;    

 public Collection<Role> getRoles() {
     return roles;
 }
}

尝试这种方式,看看它是否有效。

此外,您的查询不需要左连接,一旦您在每个实体上使用getRoles()方法(使用LAZY Fetch),JPA应自动获取角色

答案 1 :(得分:1)

实际上,为User和UserRole实体提供@ManyToMany映射是合理的。您的查询的问题是它返回连接表中我认为您不需要的所有行。因此,只需在查询中添加group by u,如下所示:

SELECT u FROM MyUser u LEFT JOIN FETCH u.roles GROUP BY u

你会完成的。