Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么Hibernate和规范会在第一个查询得到所有要求时进行两次查询?_Java_Spring Boot_Hibernate Criteria - Fatal编程技术网

Java 为什么Hibernate和规范会在第一个查询得到所有要求时进行两次查询?

Java 为什么Hibernate和规范会在第一个查询得到所有要求时进行两次查询?,java,spring-boot,hibernate-criteria,Java,Spring Boot,Hibernate Criteria,我正在做一个练习Spring引导应用程序 我有3个实体(按建议编辑): 类用户扩展EntityModelTemplate{ 字符串用户名;//唯一 @OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy=“user”) 列出用户角色; } @IdClass(UserRolesKey.class) 类用户角色{ @身份证 @许多酮 @JoinColumn(name=“user\u id”) 用户; @身份证 @manyton

我正在做一个练习Spring引导应用程序

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

类用户扩展EntityModelTemplate{
字符串用户名;//唯一
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy=“user”)
列出用户角色;
}
@IdClass(UserRolesKey.class)
类用户角色{
@身份证
@许多酮
@JoinColumn(name=“user\u id”)
用户;
@身份证
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“role\u id”)
角色;
}
类角色扩展EntityModelTemplate{
字符串角色;
@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy=“role”)
列出用户角色;
}
我想做一个单个DB调用,它将获取用户和角色,所以我尝试使用规范。我阅读了文档并在网上搜索了一些例子,然后想出了一些我想要的东西

维修方法(按建议编辑):

public UserDTO getUserForSecurityCheck(字符串username)抛出UsernameNotFoundException{
log.info(“存储库调用启动!”);
可选user=userRepo.findOne(Specification.where(UserSpecifications.usernamequals(username));
log.info(“存储库调用结束!”);
返回user.map(UserDTO::new).orelsetrow(()->newusernameNotFoundException(“Username”+Username+“NotFound!”));
}
规格:

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);
    };
}
公共静态规范usernamequals(字符串用户名){
返回(根、查询、准则生成器)->{
((Join)root.fetch(用户角色)).fetch(用户角色角色);
返回criteriaBuilder.equal(root.get(USERNAME)、USERNAME);
};
}
除了Hibernate进行两次DB调用外,它工作得非常好

(编辑)

第一个连接使用两个连接选择所需的所有内容,其中username=?(它相当长,因此是短的,短的版本)。这正是我想要它做的。 但随后它会进行第二次调用,从user_id=

为什么?

尽管我还是一个编码方面的新手,但我很确定我了解规范和Hibernate是如何工作的。至少是基础知识。显然我没有

所以,我的问题是:它应该打两个DB电话,还是我做错了什么


提前谢谢。

我发现了我的错误,我很不好意思没有马上注意到: 默认情况下,用户角色中的用户被急切地加载。这是第二个电话。我把它改成了lazy,它按预期工作


如果不是M.Deinum询问一个懒散的收藏,我在一百万年内都不会注意到它。

我发现了我的错误,我很不好意思没有立即注意到它: 默认情况下,用户角色中的用户被急切地加载。这是第二个电话。我把它改成了lazy,它按预期工作


如果不是M.Deinum询问一个懒惰的集合,我在一百万年内都不会注意到它。

请添加适当的实体(带有映射信息)。看起来您有一种复杂的方式来表达
@manytomy
。您的
角色
实体也有一个惰性集合,您并不急于加载它。这可能是由于
UserDTO
构造函数中的某些内容触发的。另一方面,不要使用
ifPresent
,而是使用
user.map(UserDTO::new).orelsetrow(新用户名notfoundexception(“Username”+Username+“notfound!”)@M.Deinum谢谢您抽出时间。我已经按照您的要求添加了适当的实体映射,并按照您的建议更改了服务方法(感谢您的提示!)。角色实体有一个惰性集合,因为每次我需要向新用户添加角色时,加载整个UserRoles列表似乎不太好。我很确定我已经读过,延迟加载不能在存储库之外完成,这应该排除UserDTO构造函数。请添加适当的实体(带有映射信息)。看起来您有一种复杂的方式来表达
@manytomy
。您的
角色
实体也有一个惰性集合,您并不急于加载它。这可能是由于
UserDTO
构造函数中的某些内容触发的。另一方面,不要使用
ifPresent
,而是使用
user.map(UserDTO::new).orelsetrow(新用户名notfoundexception(“Username”+Username+“notfound!”)@M.Deinum谢谢您抽出时间。我已经按照您的要求添加了适当的实体映射,并按照您的建议更改了服务方法(感谢您的提示!)。角色实体有一个惰性集合,因为每次我需要向新用户添加角色时,加载整个UserRoles列表似乎不太好。我很确定我已经读过,延迟加载不能在存储库之外完成,这应该排除UserDTO构造函数。
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);
    };
}