首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate @OneToOne加载,尽管它很懒

Hibernate @OneToOne加载,尽管它很懒
EN

Stack Overflow用户
提问于 2020-06-07 17:15:04
回答 1查看 1.2K关注 0票数 1

我正在使用Spring 2.3、Spring数据和Hibernate。

我有以下实体

代码语言:javascript
复制
@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;    
}

当执行以下代码时,将执行与用户存储库相关的任何查询(对我来说,这是预期的行为)。

代码语言:javascript
复制
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没有得到遵守。

代码语言:javascript
复制
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回购

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-07 17:23:59

Hibernate (或者更确切地说是PersistenceContext)需要知道实体是否存在,以便它可以决定是为实体提供代理还是为null提供代理。这不适用于XToMany关系,因为整个集合可以包装在代理中,在特殊情况下它将是空的。

同样重要的是要指出,FetchType只是对JPa实现的一个建议,没有任何保证,在每一种情况下,它都将得到实现。您可以阅读更多关于@OneToOne 这里的信息,特别是在获取策略方面:

虽然单向@OneToOne关联可以懒洋洋地获取,但是双向@OneToOne关联的父端则不是。即使在指定关联不是可选的并且我们有FetchType.LAZY时,父端关联的行为也类似于FetchType.EAGER关系。而渴望的诱惑是不好的。 即使FK不是NULL,并且父端通过可选属性(例如@OneToOne(mappedBy = "post",fetch = FetchType.LAZY,可选= false))知道它的非空性,Hibernate仍然生成一个辅助select语句。 对于每个托管实体,持久性上下文都需要实体类型和标识符,因此在加载父实体时必须知道子标识符,找到关联的post_details主键的唯一方法是执行辅助查询。 字节码增强是唯一可行的解决办法。但是,只有当父端被@LazyToOne(LazyToOneOption.NO_PROXY)注释并且子端不使用@MapsId时,它才能工作。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62248951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档