So I have a Users table, Projects table and User_Roles table. I have one users which is connected to 2 projects, but when I have just one role for him it returns those 2 projects, but if I have 2 roles for him it returns 4 roles (2x2 projects). How do I prevent this
This is my code for returning the list of projects for user
@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();
}
mappings in User class
@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;
}
Any suggestions what is the problem here?
tnx
The classic "fix" for issues of duplicate rows from criteria queries, which will likely work as long as you're not trying to combine it with pagination, is to add
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
I believe this is happening in your situation because of the eager loading of the user roles. Changing that to be lazy might also work, and continue to work if you need pagination.
Setting fetch = FetchType.EAGER
instructs hibernate that you want to always load all the roles for the user whenever you retrieve a user, which it accomplishes by always doing a join to the roles table.
Unfortunately, that sql leads to multiple records with the same user (one for each role), and it then has to be straightened out in Java after the sql is run, which is what the result transformer does.
Much more unfortunately, if you want to use paging in the most natural way with simple hibernate criteria, using criteria.setFirstResult
and criteria.setMaxResults
, things happen in the wrong order, so these queries that need the result transformer to avoid duplicates just don't page right.
To understand all the hibernate sql generation a bit better, I'd advise turning on logging of the generated sql as described in this answer to another SO hibernate question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With