1

Am I Initializing a the lazy collections properly? My main goal is to do a database query and Initialize A lazy collection so it could be used by methods that does not have a DB session.

My current method works but it seems to be querying the database multiple times. Can anyone confirm this is correct or show me the proper way.

Service Class Methods

    public void testing() {
    
        try {
            List<User> users = test();
    
            for (User user : users) {
                System.out.println(user);
                Set<UserGroupMapping> userGroupMapping   = user.getUserGroupMappings();
    
                for (UserGroupMapping userGroupMapping : userGroupMapping) {
                    System.out.println(userGroupMapping);
                }
    
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    
    }

@Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true)
private List<User> test() {
    return  dao.findUsers();    
}

Dao Class Method

@Transactional(value = "transactionManager", propagation = Propagation.MANDATORY, isolation = Isolation.DEFAULT, readOnly = true)
public List<User> findUsers() {
    Criteria criteria = getCesSession().createCriteria(User.class);
    
            criteria.setFetchMode("userGroupMappings", FetchMode.SELECT);
    
            @SuppressWarnings("unchecked")
            List<User> list = (List<User>) criteriaList(criteria);
    
            for (User user : list) {
                Set<UserGroupMapping> b = user.getUserGroupMappings();
    
                Hibernate.initialize(b);
    
                for (UserGroupMapping userGroupMapping : b) {
                    Hibernate.initialize(userGroupMapping.getGroup());
                }
    
            }
    
            return list;
        }

User Entity

@Entity
@Table(name = "[User]", schema = "dbo", catalog = "Test", uniqueConstraints = @UniqueConstraint(columnNames = "userName"))
public class User extends DatabaseObject {

    private Long userId;
    private Set<UserGroupMapping> userGroupMappings = new HashSet<UserGroupMapping>(
            0);

    @Id
    @Column(name = "userId", unique = true, nullable = false)
    public Long getUserId() {
        return this.userId;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    public Set<UserGroupMapping> getUserGroupMappings() {
        return this.userGroupMappings;
    }

Group Entity

@Entity
@Table(name = "[Group]", schema = "dbo", catalog = "Test", uniqueConstraints = @UniqueConstraint(columnNames = "name"))
public class Group extends DatabaseObject {

    private Long groupId;
    private Set<GroupRoleMapping> groupRoleMappings = new HashSet<GroupRoleMapping>(0);
    private Set<UserGroupMapping> userGroupMappings = new HashSet<UserGroupMapping>(0);

    @Id
    @Column(name = "groupId", unique = true, nullable = false)
    public Long getGroupId() {
        return this.groupId;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "group")
    public Set<GroupRoleMapping> getGroupRoleMappings() {
        return this.groupRoleMappings;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "group")
    public Set<UserGroupMapping> getUserGroupMappings() {
        return this.userGroupMappings;
    }

UserGroupMapping Entity

@Entity
@Table(name = "UserGroupMapping", schema = "dbo", catalog = "Test", uniqueConstraints = @UniqueConstraint(columnNames = "userId"))
public class UserGroupMapping extends DatabaseObject {

    private Long userGroupMappingId;
    private Group group;
    private User user;

    @Id
    @Column(name = "userGroupMappingId", unique = true, nullable = false)
    public Long getUserGroupMappingId() {
        return this.userGroupMappingId;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "groupId", nullable = false)
    public Group getGroup() {
        return this.group;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "userId", unique = true, nullable = false)
    public User getUser() {
        return this.user;
    }
}

LOGS

DEBUG: 15:19:22.251 - 
    /* criteria query */ select
        this_.userId as userId1_17_0_,
        this_.createdBy as createdB2_17_0_,
        this_.dateCreated as dateCrea3_17_0_,
        this_.dateUpdated as dateUpda4_17_0_,
        this_.name as name5_17_0_,
        this_.password as password6_17_0_,
        this_.updatedBy as updatedB7_17_0_,
        this_.userName as userName8_17_0_ 
    from
        CES_SIT.dbo.[User] this_
Hibernate: 
    /* criteria query */ select
        this_.userId as userId1_17_0_,
        this_.createdBy as createdB2_17_0_,
        this_.dateCreated as dateCrea3_17_0_,
        this_.dateUpdated as dateUpda4_17_0_,
        this_.name as name5_17_0_,
        this_.password as password6_17_0_,
        this_.updatedBy as updatedB7_17_0_,
        this_.userName as userName8_17_0_ 
    from
        CES_SIT.dbo.[User] this_




    DEBUG: 15:19:39.159 - 
        select
            usergroupm0_.userId as userId7_17_0_,
            usergroupm0_.userGroupMappingId as userGrou1_15_0_,
            usergroupm0_.userGroupMappingId as userGrou1_15_1_,
            usergroupm0_.createdBy as createdB2_15_1_,
            usergroupm0_.dateCreated as dateCrea3_15_1_,
            usergroupm0_.dateUpdated as dateUpda4_15_1_,
            usergroupm0_.groupId as groupId6_15_1_,
            usergroupm0_.updatedBy as updatedB5_15_1_,
            usergroupm0_.userId as userId7_15_1_ 
        from
            CES_SIT.dbo.UserGroupMapping usergroupm0_ 
        where
            usergroupm0_.userId=?
    Hibernate: 
        select
            usergroupm0_.userId as userId7_17_0_,
            usergroupm0_.userGroupMappingId as userGrou1_15_0_,
            usergroupm0_.userGroupMappingId as userGrou1_15_1_,
            usergroupm0_.createdBy as createdB2_15_1_,
            usergroupm0_.dateCreated as dateCrea3_15_1_,
            usergroupm0_.dateUpdated as dateUpda4_15_1_,
            usergroupm0_.groupId as groupId6_15_1_,
            usergroupm0_.updatedBy as updatedB5_15_1_,
            usergroupm0_.userId as userId7_15_1_ 
        from
            CES_SIT.dbo.UserGroupMapping usergroupm0_ 
        where
            usergroupm0_.userId=?



    DEBUG: 15:19:39.176 - Preparing collection intializer : [com.bdo.ces.entities.User.userGroupMappings#1]
    DEBUG: 15:19:39.176 - Starting ResultSet row #0
    DEBUG: 15:19:39.177 - Found row of collection: [com.bdo.ces.entities.User.userGroupMappings#1]
    DEBUG: 15:19:39.177 - Resolving associations for [com.bdo.ces.entities.UserGroupMapping#1]
    DEBUG: 15:19:39.177 - Done materializing entity [com.bdo.ces.entities.UserGroupMapping#1]
    DEBUG: 15:19:39.177 - 1 collections were found in result set for role: com.bdo.ces.entities.User.userGroupMappings
    DEBUG: 15:19:39.177 - Collection fully initialized: [com.bdo.ces.entities.User.userGroupMappings#1]
    DEBUG: 15:19:39.177 - 1 collections initialized for role: com.bdo.ces.entities.User.userGroupMappings
    DEBUG: 15:19:39.177 - Done loading collection
    DEBUG: 15:19:39.177 - Initializing proxy: [com.bdo.ces.entities.Group#1]
    DEBUG: 15:19:39.177 - 
        select
            group0_.groupId as groupId1_16_0_,
            group0_.createdBy as createdB2_16_0_,
            group0_.dateCreated as dateCrea3_16_0_,
            group0_.dateUpdated as dateUpda4_16_0_,
            group0_.description as descript5_16_0_,
            group0_.name as name6_16_0_,
            group0_.updatedBy as updatedB7_16_0_,
            group0_.visible as visible8_16_0_ 
        from
            CES_SIT.dbo.[
        Group] group0_ where
            group0_.groupId=?
    Hibernate: 
        select
            group0_.groupId as groupId1_16_0_,
            group0_.createdBy as createdB2_16_0_,
            group0_.dateCreated as dateCrea3_16_0_,
            group0_.dateUpdated as dateUpda4_16_0_,
            group0_.description as descript5_16_0_,
            group0_.name as name6_16_0_,
            group0_.updatedBy as updatedB7_16_0_,
            group0_.visible as visible8_16_0_ 
        from
            CES_SIT.dbo.[
        Group] group0_ where
            group0_.groupId=?

Testing With K.C================================

Dao Class Method

@Transactional(value = "transactionManager", propagation = Propagation.MANDATORY, isolation = Isolation.DEFAULT, readOnly = true)
        public List<User> findUsers() {
    Criteria criteria = getCesSession().createCriteria(User.class);
    
            criteria.setFetchMode("userGroupMappings", FetchMode.JOIN);
    
            criteria.createAlias("userGroupMappings", "userGroupMappings",
                    JoinType.LEFT_OUTER_JOIN);
    
            @SuppressWarnings("unchecked")
            List<User> list = (List<User>) criteriaList(criteria);
    
            Hibernate.initialize(list);
    
            for (User user : list) {
                Set<UserGroupMapping> b = user.getUserGroupMappings();
                
                Hibernate.initialize(b);
    
                for (UserGroupMapping userGroupMapping : b) {
                    Hibernate.initialize(userGroupMapping.getGroup());
                }
    
            }
    
            return list; 
    
                }

LOGS

DEBUG: 17:40:19.989 - 
    /* criteria query */ select
        this_.userId as userId1_17_1_,
        this_.createdBy as createdB2_17_1_,
        this_.dateCreated as dateCrea3_17_1_,
        this_.dateUpdated as dateUpda4_17_1_,
        this_.name as name5_17_1_,
        this_.password as password6_17_1_,
        this_.updatedBy as updatedB7_17_1_,
        this_.userName as userName8_17_1_,
        usergroupm1_.userId as userId7_17_3_,
        usergroupm1_.userGroupMappingId as userGrou1_15_3_,
        usergroupm1_.userGroupMappingId as userGrou1_15_0_,
        usergroupm1_.createdBy as createdB2_15_0_,
        usergroupm1_.dateCreated as dateCrea3_15_0_,
        usergroupm1_.dateUpdated as dateUpda4_15_0_,
        usergroupm1_.groupId as groupId6_15_0_,
        usergroupm1_.updatedBy as updatedB5_15_0_,
        usergroupm1_.userId as userId7_15_0_ 
    from
        CES_SIT.dbo.[User] this_ 
    left outer join
        CES_SIT.dbo.UserGroupMapping usergroupm1_ 
            on this_.userId=usergroupm1_.userId
Hibernate: 
    /* criteria query */ select
        this_.userId as userId1_17_1_,
        this_.createdBy as createdB2_17_1_,
        this_.dateCreated as dateCrea3_17_1_,
        this_.dateUpdated as dateUpda4_17_1_,
        this_.name as name5_17_1_,
        this_.password as password6_17_1_,
        this_.updatedBy as updatedB7_17_1_,
        this_.userName as userName8_17_1_,
        usergroupm1_.userId as userId7_17_3_,
        usergroupm1_.userGroupMappingId as userGrou1_15_3_,
        usergroupm1_.userGroupMappingId as userGrou1_15_0_,
        usergroupm1_.createdBy as createdB2_15_0_,
        usergroupm1_.dateCreated as dateCrea3_15_0_,
        usergroupm1_.dateUpdated as dateUpda4_15_0_,
        usergroupm1_.groupId as groupId6_15_0_,
        usergroupm1_.updatedBy as updatedB5_15_0_,
        usergroupm1_.userId as userId7_15_0_ 
    from
        CES_SIT.dbo.[User] this_ 
    left outer join
        CES_SIT.dbo.UserGroupMapping usergroupm1_ 
            on this_.userId=usergroupm1_.userId


    select
        group0_.groupId as groupId1_16_0_,
        group0_.createdBy as createdB2_16_0_,
        group0_.dateCreated as dateCrea3_16_0_,
        group0_.dateUpdated as dateUpda4_16_0_,
        group0_.description as descript5_16_0_,
        group0_.name as name6_16_0_,
        group0_.updatedBy as updatedB7_16_0_,
        group0_.visible as visible8_16_0_ 
    from
        CES_SIT.dbo.[
    Group] group0_ where
        group0_.groupId=?
Hibernate: 
    select
        group0_.groupId as groupId1_16_0_,
        group0_.createdBy as createdB2_16_0_,
        group0_.dateCreated as dateCrea3_16_0_,
        group0_.dateUpdated as dateUpda4_16_0_,
        group0_.description as descript5_16_0_,
        group0_.name as name6_16_0_,
        group0_.updatedBy as updatedB7_16_0_,
        group0_.visible as visible8_16_0_ 
    from
        CES_SIT.dbo.[
    Group] group0_ where
        group0_.groupId=?

DEBUG: 17:40:38.189 - 
    select
        group0_.groupId as groupId1_16_0_,
        group0_.createdBy as createdB2_16_0_,
        group0_.dateCreated as dateCrea3_16_0_,
        group0_.dateUpdated as dateUpda4_16_0_,
        group0_.description as descript5_16_0_,
        group0_.name as name6_16_0_,
        group0_.updatedBy as updatedB7_16_0_,
        group0_.visible as visible8_16_0_ 
    from
        CES_SIT.dbo.[
    Group] group0_ where
        group0_.groupId=?
Hibernate: 
    select
        group0_.groupId as groupId1_16_0_,
        group0_.createdBy as createdB2_16_0_,
        group0_.dateCreated as dateCrea3_16_0_,
        group0_.dateUpdated as dateUpda4_16_0_,
        group0_.description as descript5_16_0_,
        group0_.name as name6_16_0_,
        group0_.updatedBy as updatedB7_16_0_,
        group0_.visible as visible8_16_0_ 
    from
        CES_SIT.dbo.[
    Group] group0_ where
        group0_.groupId=?
DEBUG: 17:40:38.197 - Starting ResultSet row #0

FINAL ============================

Got This to work using this code I'm still not exactly sure if this is the best way of doing it but it loads the lazy collection in just one query. I also joined the lazy object in [userGroupMappings.group] to make it work.

I thought Hibernate.initialize() would do that for me but it didn't.

**Dao Class Method**


    @Transactional(value = "transactionManager", propagation = Propagation.MANDATORY, isolation = Isolation.DEFAULT, readOnly = true)
            public List<User> findUsers() {
        Criteria criteria = getCesSession().createCriteria(User.class);
                            
                criteria.createCriteria("userGroupMappings", "userGroupMappings",
                        JoinType.LEFT_OUTER_JOIN);
                criteria.createCriteria("userGroupMappings.group", "userGroupMappings.group",
                        JoinType.LEFT_OUTER_JOIN);
        
                @SuppressWarnings("unchecked")
                List<User> list = (List<User>) criteriaList(criteria);
        
                
       
                return list; 
        
                    }
Community
  • 1
  • 1
Jefrey Valencia
  • 713
  • 3
  • 13
  • 30

1 Answers1

1

Because of the User - UserGroupMapping 1 - n mapping, you have n + 1 select issue, described here. That's why you have so many queries.

You can avoid this by doing a left outer join on the UserGroupMapping.

K.C.
  • 2,084
  • 2
  • 25
  • 38
  • Hi thanks for the response. I'm searching left outer join using Criteria I will try it out. – Jefrey Valencia Jun 11 '14 at 07:47
  • Hi K.C I tried adding criteria.createAlias("userGroupMappings", "userGroupMappings",JoinType.LEFT_OUTER_JOIN); but I still seem to be querying the database multiple times. As the application will still wont work if I remove the foreach loop holding Hibernate.initialize(userGroupMapping.getGroup()); Could you show me an example? – Jefrey Valencia Jun 11 '14 at 08:29
  • Try .setFetchMode("userGroupMappings", FetchMode.JOIN) in your Dao – K.C. Jun 11 '14 at 09:25
  • Hi K.C I tried your suggestion but It still seems that my app is still hitting the database multiple times. Could you check If I was able to properly implement your suggestion. I updated my code above. I believe this is due to Hibernate.initialize(userGroupMapping.getGroup()) but without it I would get the LazyDataInitializationException. Thank you for your patience. – Jefrey Valencia Jun 11 '14 at 09:50
  • Instead of the createAlias, try criteria.createCriteria("userGroupMappings", "ugm", JoinType.LEFT_OUTER_JOIN).list(); That way, the generated query will do an outer join of User on UserGroupMappings – K.C. Jun 11 '14 at 11:19