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) 个答案