[英]Hibernate @OneToOne loaded even though is lazy
我正在使用 Spring Boot 2.3、Spring 数据和 Hibernate。
我有以下实体
@Entity
@Getter
@Setter
@EqualsAndHashCode(of = "id")
public class User {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
private String name;
@OneToOne(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Address address;
@Version
private Long version;
}
@Entity
@Getter
@Setter
@EqualsAndHashCode(of = "id")
public class Address {
@Id
private Long id;
private String fullAddress;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id")
@MapsId
private User user;
@Version
private Long version;
}
执行以下代码时,将执行与用户存储库相关的任何查询(对我来说这是预期的行为)。
Address addressFromDb = addressRepository.findAll().get(0);
log.info("" + addressFromDb.getUser().getId());
// select address0_.id as id1_0_, address0_.full_address as full_add2_0_, address0_.version as version3_0_ from address address0_
但是当我执行以下代码时,会有多个查询,我不明白为什么。 显然,从用户到地址的FetchType.LAZY
不受尊重。
User userFromDb = userRepository.findAll().get(0);
// select user0_.id as id1_4_, user0_.name as name2_4_, user0_.version as version3_4_ from user user0_
// select address0_.id as id1_0_0_, address0_.full_address as full_add2_0_0_, address0_.version as version3_0_0_ from address address0_ where address0_.id=?
我错过了什么?
为了更有帮助和更清楚,我创建了以下github repo
Hibernate (或更具体地说是PersistenceContext
)需要知道实体是否存在,以便它可以决定是为实体提供代理还是null
。 这不适用于XToMany
关系,因为整个集合可以包装在代理中,在特殊情况下它将为空。
还需要指出的是, FetchType
只是对 JPa 实现的建议,不能保证在任何情况下都会实现。 您可以在此处阅读有关@OneToOne
的更多信息,尤其是在获取策略方面:
虽然可以延迟获取单向 @OneToOne 关联,但双向 @OneToOne 关联的父端却不能。 即使指定关联不是可选的并且我们有 FetchType.LAZY,父端关联的行为也类似于 FetchType.EAGER 关系。 EAGER fetching 很糟糕。
即使 FK 不是 NULL 并且父端通过可选属性(例如 @OneToOne(mappedBy = "post", fetch = FetchType.LAZY, optional = false))知道其不可为空性,Hibernate 仍然会生成二级 select 语句。
对于每一个托管实体,Persistence Context 都需要实体类型和标识符,因此在加载父实体时必须知道子标识符,而找到关联的 post_details 主键的唯一方法是执行二级查询。
字节码增强是唯一可行的解决方法。 但是,它仅在父端使用 @LazyToOne(LazyToOneOption.NO_PROXY) 注释并且子端未使用 @MapsId 时才有效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.