Search code examples
javahibernateormmany-to-many

Hibernate Criteria - Many to Many relations


I'm trying to use Hibernate Criteria for a select using tables related in a many-to-many relation. The n-m table has some additional columns not just the id's from each of the tables.

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(Fornecedor.class);
Root<User> root = criteria.from(User.class );
criteria.select(root);
root.fetch("userRolesList");
List<User> users = em.createQuery(criteria).getResultList();

In User class I have the userRolesList (n-m table) which has the roles. So I have User -> UserRoles -> Role. Every property are mapped as FetchType.LAZY

  1. When I try to print the user roles, for example, hibernate throws the org.hibernate.LazyInitializationException cause the roles where not fetched.

  2. When I change code for the one that follows.

code:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(Fornecedor.class);
Root<User> root = criteria.from(User.class );
criteria.select(root);    
root.fetch("userRolesList");
root.fetch("userRolesList.role");
List<User> users = em.createQuery(criteria).getResultList();

then I get:

java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [userRolesList.role] on this ManagedType [User]

I have tryed many options for the situation like joins, but still couldn't make it work.


Solution

  • It seems you are trying to go a bit too far with the fetching.

    Try doing it in baby steps:

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<User> criteria = builder.createQuery(Fornecedor.class);
    
    Root<User> root = criteria.from(User.class );
    criteria.select(root);
    
    Fetch<User, UserRoles> userRolesFetch = root.fetch("userRolesList", JoinType.INNER);
    Fetch<UserRoles, Role> roleFetch = userRolesFetch.fetch("role", JoinType.INNER);
    
    List<User> users = em.createQuery(criteria).getResultList();