Правильная инициализация коллекций Hibernate Lazy

Правильно ли я инициализирую ленивые коллекции? Моя основная цель - выполнить запрос к базе данных и инициализировать ленивую коллекцию, чтобы ее можно было использовать методами, у которых нет сеанса БД.

Мой текущий метод работает, но, похоже, он несколько раз запрашивает базу данных. Может ли кто-нибудь подтвердить, что это правильно, или показать мне правильный путь.

Методы класса обслуживания

    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();    
}

Метод класса Дао

@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;
        }

Объект пользователя

@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;
    }

Группа

@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
@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;
    }
}

ЖУРНАЛЫ

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=?

Тестирование с K.C================================

Метод класса Дао

@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; 
    
                }

ЖУРНАЛЫ

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

ФИНАЛ =============================

Получил это для работы с использованием этого кода. Я до сих пор не совсем уверен, что это лучший способ сделать это, но он загружает ленивую коллекцию всего за один запрос. Я также присоединился к ленивому объекту в [userGroupMappings.group], чтобы заставить его работать.

Я думал, что Hibernate.initialize() сделает это за меня, но это не так.

**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; 
        
                    }

person Jefrey Valencia    schedule 11.06.2014    source источник


Ответы (1)


Из-за отображения User - UserGroupMapping 1 - n у вас есть проблема выбора n + 1, описанная здесь< /а>. Вот почему у вас так много запросов.

Этого можно избежать, выполнив левое внешнее соединение с UserGroupMapping.

person K.C.    schedule 11.06.2014
comment
Привет, спасибо за ответ. Я ищу левое внешнее соединение, используя критерии. Я попробую. - person Jefrey Valencia; 11.06.2014
comment
Привет, К.С. Я попытался добавить критерии.createAlias(userGroupMappings, userGroupMappings,JoinType.LEFT_OUTER_JOIN); но я все еще, кажется, запрашиваю базу данных несколько раз. Поскольку приложение все равно не будет работать, если я удалю цикл foreach, содержащий Hibernate.initialize(userGroupMapping.getGroup()); Не могли бы вы показать мне пример? - person Jefrey Valencia; 11.06.2014
comment
Попробуйте .setFetchMode(userGroupMappings, FetchMode.JOIN) в вашем Dao - person K.C.; 11.06.2014
comment
Привет, KC. Я попробовал ваше предложение, но все еще кажется, что мое приложение все еще несколько раз попадает в базу данных. Не могли бы вы проверить, смог ли я правильно реализовать ваше предложение. Я обновил свой код выше. Я считаю, что это связано с Hibernate.initialize(userGroupMapping.getGroup()), но без него я бы получил исключение LazyDataInitializationException. Спасибо за терпеливость. - person Jefrey Valencia; 11.06.2014
comment
Вместо createAlias ​​попробуйте критерии.createCriteria(userGroupMappings, ugm, JoinType.LEFT_OUTER_JOIN).list(); Таким образом, сгенерированный запрос выполнит внешнее соединение пользователя с UserGroupMappings. - person K.C.; 11.06.2014