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

问题描述:

我有一个很奇怪的问题。当列出一个类的所有实体时,JPA返回同一实例的多个对象

我有一个具有子实体列表的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,角色的实体是非常简单的。

@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数据库。

有没有人看过类似的问题?

我觉得你有你的模型错了,通常是用户角色关系不是一对多,但“多对多”,所以你应该改变你的代码看起来是这样的:

@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; 
} 
} 

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

而且您的查询应该不需要左加入,角色应自动JPA一旦你使用getRoles()方法对每个实体(使用LAZY获取)

+0

谢谢。 @ManyToMany是正确的,是的。增加了@ManyToMany(casscade = CascadeType.ALL,fetch = FetchType.EAGER),并解决了这个问题。 – 2012-08-13 13:37:55

+0

太棒了!我很高兴为你工作! – 2012-08-14 02:14:05

其实,这是合理的做法是取@用户和UserRole实体的ManyToMany映射。你的查询的问题是,它返回连接表中的所有行,我相信你不需要。所以只需添加group by u到您的查询,如下所示:

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

,你会做。