In our example we want to retrieve Users that are assigned a particular Authority, like role_admin, role_user, etc. We need to include ALL Authorities of the User. Expressed another way, we want all Parent data and all Child Objects, but only Parent Objects with a given Child.
Our User table has a @ManyToMany relationship with Authorities through a user_authorities table.
In our User Model we define the @ManyToMany with FetchType.EAGER because we always want our Authorities contained in our User object.
If we want all child objects in a @Query statement we would normally include a fetch directive, like so.
But when we want to retrieve all users that are assigned ROLE_USER with the above query we would retrieve all User data for the user object but only the ROLE_USER Authority. Our Admin User would as a result of this query appear to be assigned the ROLE_USER Authority only.
We could do a userRepository.findAll() and then filter out the users containing our role with a Java Stream.
But there’s a much more simple approach by letting Hibernate do its thing. Because we defined the @ManyToMany relationship of Users to Authorities as EAGER, we already have the Child Objects at our disposal. Instead of performing a fresh fetch on the Child Objects for authority_id = id, we’re essentially querying our Persistence Context. (No left join fetch.)
This retrieves what we want: All users, including ALL of their authorities, who are assigned a given authority by id. And cleaner Controller code as well. No streaming required.
As a bonus bit of code, if you’re interested in the task at hand of deleting a ROLE and removing its assignment to any User prior to its deletion, here is the Service method.