为什么 Hibernate with Specification 在第一个查询得到所有要求时进行两次查询?

Why is Hibernate with Specification making two queries when the first one got everything that was asked?

我正在练习Spring启动应用程序。

我有 3 个实体(按建议编辑):

class User extends EntityModelTemplate {
   String username; //unique

   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
   List<UserRoles> userRoles; 
}

@IdClass(UserRolesKey.class)
class UserRoles {

   @Id
   @ManyToOne
   @JoinColumn(name = "user_id")
   User user;

   @Id
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "role_id")
   Role role;
}


class Role extends EntityModelTemplate{
   String role;

   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "role")
   List<UserRoles> userRoles;
}

我想做一个 单一 数据库调用,它会获取用户和角色,所以我尝试使用规范。我阅读了文档并在线搜索了示例,然后提出了一些应该像我想要的那样工作的东西。

服务方式(推荐编辑):

public UserDTO getUserForSecurityCheck(String username) throws UsernameNotFoundException {
    log.info("Repository call start!");
    Optional<User> user = userRepo.findOne(Specification.where(UserSpecifications.usernameEquals(username)));
    log.info("Repository call end!");
    return user.map(UserDTO::new).orElseThrow(() -> new UsernameNotFoundException("Username "+username+" not found!"));
}

规格:

public static Specification<User> usernameEquals(String username){

    return (root, query, criteriaBuilder) -> {
        ( (Join<Object, Object>) root.fetch(User_.USER_ROLES)).fetch(UserRoles_.ROLE);
        return criteriaBuilder.equal(root.get(User_.USERNAME), username);
    };
}

除了 Hibernate 进行两次数据库调用外,它工作得很好。

(编辑)

第一个使用两个连接选择所有需要的,其中 username=? (它相当长,因此是短版)。这正是我想要它做的。 但随后它进行了第二次调用,从字面上执行 Select *(userRoles 除外) from user where user_id=?.

为什么?

虽然我在一般编码方面仍然是新手,但我非常确定我了解规范和 Hibernate 的工作原理。至少是基础知识。显然我不知道。

所以,我的问题是:是应该进行两次数据库调用还是我做错了什么?

提前致谢。

我发现了我的错误,我为没有立即注意到它而感到非常尴尬: 默认情况下,UserRoles 中的用户是急切加载的。那是第二个电话。我将其更改为懒惰并且按预期工作。

要不是M.Deinum问一个懒人collection,我一百万年都不会注意到它。