【问题标题】:JPA returns multiple objects of the same instance when listing all entities of a class列出类的所有实体时,JPA 返回同一实例的多个对象
【发布时间】:2012-08-09 15:01:39
【问题描述】:

我有一个带有子实体列表的 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;
 }
}

如果感兴趣,角色实体很简单。

@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 数据库一起使用。

【问题讨论】:

    标签: jpa persistence db2


    【解决方案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;
     }
    }
    

    试试这个方法,看看是否有效。

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

    【讨论】:

    • 谢谢。 @ManyToMany 是正确的,是的。添加了@ManyToMany(casscade=CascadeType.ALL,fetch=FetchType.EAGER) 解决了这个问题。
    【解决方案2】:

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

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

    你就完成了。

    【讨论】:

      猜你喜欢
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多