Question

I have the following Hibernate entities: User, Role and Team. There is also the UserTeamRole entity which is basically a connection between a User, his Role and the Team he is in:

@Entity
@Table(name = "user_team_role")
public class UserTeamRole {

    private Long id;
    private User user;
    private Role role;
    private Team team;
    [...]  
}

In my JSF managed bean I need to get the User and all the UserTeamRoles for a particular user designated name that I get in a form. I do that in the UserDAO:

public User getUserByDn(String dn) {
        User result = (User) getSessionFactory().getCurrentSession()
                .createCriteria(User.class)
                .setFetchMode("userTeamRoles", FetchMode.JOIN)
                .add(Restrictions.like("dn", dn)).uniqueResult();
        return result;
    }

I used the FetchMode because otherwise I would get a LazyInitializationException in the bean because the session was closed at the point that I would need to access the collection.

But, after this I also need to loop through this User.userTeamRoles collection and get the name for each role.

When I do this:

    if (null != u.getUserTeamRoles()) {
        for (UserTeamRole urt : u.getUserTeamRoles()) {
            // here get role for every UserTeamRole

            grAuth.add(new SimpleGrantedAuthority(urt.getRole().getName()));
        }
   }

I get an exception:

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy - no Session for the Role entity.

So my question is how can I also get the Role for each UserTeamRole like I did here .setFetchMode("userTeamRoles", FetchMode.JOIN) in getUserByDn.

I tried "chaining" the call to FetchMode but it does not work. I saw you can chain queries on members of associations, but I don't need to query, I just need the Role to be initialized so I can use it further.

I'm using Hibernate 4, Spring 3, JSF 2.

Thanks

Was it helpful?

Solution

You need to create an alias:

Criteria c = getSessionFactory().getCurrentSession().createCriteria(User.class, "user");
c.setFetchMode("user.userTeamRoles", FetchMode.JOIN);
c.createAlias("user.userTeamRoles", "utr", CriteriaSpecification.LEFT_JOIN);
c.setFetchMode("utr.role", FetchMode.JOIN);
c.add(Restrictions.like("dn", dn));

The corresponding HQL query is very similar, but much easier to read and understand IMO:

select distinct user from User user
left join fetch user.userTeamRoles utr
left join fetch utr.role
where user.dn like :dn

OTHER TIPS

Posting the answer now so that someone can get help related to Criteria api fetching associated lazy collection. I am using hibernate-4.3.11.Final

The following criteria query works :

Criteria c = getSessionFactory().getCurrentSession().createCriteria(User.class, "user");
c.setFetchMode("user.userTeamRoles", FetchMode.JOIN);
c.createAlias("user.userTeamRoles", "utr", JoinType.LEFT_OUTER_JOIN);
c.setFetchMode("utr.role", FetchMode.JOIN);
c.createAlias("utr.role", "role", JoinType.LEFT_OUTER_JOIN);
c.add(Restrictions.like("dn", dn));
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); // optional.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top