5

所以我有一个用户表、项目表和用户角色表。我有一个用户连接到 2 个项目,但是当我只有一个角色给他时,它会返回这 2 个项目,但是如果我有 2 个角色给他,它会返回 4 个角色(2x2 项目)。我该如何防止这种情况

这是我为用户返回项目列表的代码

@Override
public List<Project> retrieve(User user) {
    Criteria criteria = super.createCriteria();
    criteria.addOrder(Order.desc("date"));
    criteria.createCriteria("users").add(Restrictions.eq("id", user.getId()));

    return (List<Project>) criteria.list();
}

用户类中的映射

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "Users_Projects",
           joinColumns = @JoinColumn(name = "UserID"), inverseJoinColumns =   @JoinColumn(name = "ProjectID"))
public List<Project> getProjects() {
    return projects;
} 

@ElementCollection(fetch = FetchType.EAGER)
@Enumerated(EnumType.STRING)
@Column(name = "RoleType")
@JoinTable(name = "User_Roles", joinColumns = @JoinColumn(name = "UserID"))
public Set<Role> getRoles() {
    return roles;
}

任何建议这里有什么问题?

tnx

4

1 回答 1

13

标准查询中重复行问题的经典“修复”,只要您不尝试将它与分页结合起来,它可能会起作用,是添加

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

我相信由于用户角色的急切加载,您的情况正在发生这种情况。将其更改为惰性也可能有效,如果您需要分页,则继续工作。

设置fetch = FetchType.EAGER指示 hibernate 在检索用户时始终为用户加载所有角色,它通过始终连接角色表来完成。

不幸的是,该 sql 导致具有相同用户的多条记录(每个角色一个),然后必须在运行 sql 后在 Java 中理顺,这就是结果转换器的作用。

更不幸的是,如果您想通过简单的休眠条件以最自然的方式使用分页,使用criteria.setFirstResultand criteria.setMaxResults,事情会以错误的顺序发生,因此这些需要结果转换器以避免重复的查询只是不正确分页。

为了更好地理解所有休眠 sql 生成,我建议打开生成的 sql 的日志记录,如this answer to another SO hibernate question中所述。

于 2012-07-03T22:14:11.073 回答