我有一个带有子实体列表的 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;
}
}
如果有趣的话,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 数据库一起使用。
最佳答案
我认为您的模型错误,通常用户角色关系不是 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 应自动获取角色
关于JPA 在列出类的所有实体时返回同一实例的多个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11886306/