有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何防止对OneTONE关系进行额外查询

我有桌子:

users (id, name, email, password)
user_statuses (user_id, is_premium, is_advanced, user_rank_id)
user_ranks (id, name, ordinal)

用户和用户状态之间的关系是1-1,我有以下实体类别:

@Entity
@Table(name = "users")
@Getter
@Setter
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String name;
    private String email;
    private String password;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private UserStatus status;
}

@Entity
@Table(name = "user_statuses")
@Getter
@Setter
@NoArgsConstructor
public class UserStatus {
    @Id
    private long id;

    @MapsId
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    private boolean isPremium;
    private boolean isAdvanced;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_rank_id")
    private UserRank rank;
}

@Entity
@Table(name = "user_ranks")
@Getter
@Setter
@NoArgsConstructor
public class UserRank {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String name;
    private int ordinal;
}

然后我创建了端点“/users/{id}”,它应该以字符串形式返回用户的电子邮件地址:

@GetMapping("/users/{id}")
public String getUserEmail(@PathVariable("id") long userId) {
    User user = service.getUser(userId);
    return user.getEmail();
}

当我调用上述端点时,我得到了用户的电子邮件地址作为响应,但是查看控制台日志,我看到hibernate执行了2个查询,但没有人要求他这样做:

第一个用于获取用户的选项:

SELECT
    user0_.id AS id1_2_0_,
    user0_.email AS email2_2_0_,
    user0_.name AS name3_2_0_,
    user0_.password AS password4_2_0_
FROM
    users user0_
WHERE
    user0_.id = 1;

第二个用于获取与此用户对象关联的用户状态:

SELECT
    userstatus0_.user_id AS user_id1_1_0_,
    userstatus0_.is_advanced AS is_advan2_1_0_,
    userstatus0_.is_premium AS is_premi3_1_0_,
    userstatus0_.user_rank_id AS user_ran4_1_0_
FROM
    user_statuses userstatus0_
WHERE
    userstatus0_.user_id = 1;

所以我很困惑:当我在每个关系上设置fetch = FetchType.LAZY时,为什么hibernate运行第二个查询。。。看起来@OneToOne注释忽略了LAZY

我不使用EntityGraph

如何停止hibernate以运行第二个查询

编辑

所以,Hibernate忽略了我的惰性提示,因为它需要决定是用NULL还是ProxyObject初始化属性,这是有意义的。这个链接很好地解释了这一点:

https://thorben-janssen.com/hibernate-tip-lazy-loading-one-to-one/

然而,该链接还表明,建模的最佳方式是单向一对一,它表示我可以始终基于用户ID获取UserStatus(因为两个表“共享”主键)

但是这让我有点困惑,因为我可以使用单个查询(SELECT * FROM users LEFT JOIN user_statuses ON users.id = user_statuses.user_id)获取两行,但是使用链接中描述的方法,我需要两个查询,据我所知(我可能错了),1个查询比执行2个查询更好,而且如果我想获取25个用户及其用户状态,那么我还需要2个查询,一个用于获取用户,然后获取CoreSBinding用户状态,最后为每个循环编写嵌套以连接这些对象。我可以只执行一个查询来获取所有内容


共 (0) 个答案