JPA OneToOne懒惰关系

时间:2015-09-30 14:55:31

标签: java hibernate jpa

我有两个实体:用户 UserProfile ,它们之间具有双向@OneToOne关系。
由于一些旧的DB设计,UserProfile是所有者(我在users_profiles表中有user_id列)
   这个关系是懒惰的,因为我有fetchType Lazy和optional = false 一切都按预期工作,我的意思是当我加载UserProfile时它也不会自动加载用户。我想这是完全正常的,因为我从主人那边加载 我的问题是,如果我加载用户(拥有方),它会自动加载UserProfile,尽管关系是懒惰的。

我的意思是:当我从自有方加载实体以加载所有者实体时,这是正常的吗?

@Entity
@Table(name = "users")
public class User extends BaseEntity implements Serializable {

    @OneToOne(mappedBy = "user", optional=false, fetch = FetchType.LAZY) 
    private UserProfile profile;
    // .................rest of entity 
 }




@Entity
@Table(name="users_profiles")
public class UserProfile extends BaseEntity implements Serializable {

    @OneToOne(optional=false, fetch = FetchType.LAZY)
    @JoinColumn(name="user_id")
    private User user;
    // ... rest of entity here 
}

我测试它的方法是使用EntityManager方法find(id)加载User实体 我注意到,当关系不是懒惰时,我只有一个查询内部有一个连接。如果我放置当前设置,我有两个单独的查询:1表示用户,另一个表示配置文件。

2 个答案:

答案 0 :(得分:1)

重要的是要意识到,JPA规范并未强制执行延迟加载行为,仅建议使用它。它是由hibernate作为实现来选择它是否受支持以及在哪些条件下。

Hibernate通常会在请求时懒得加载数据,但是在one-to-one映射的情况下,当关系存储在另一个表中时(主键在表users_profiles中),它还需要查询第二个表以检索主键以创建代理对象。实际上,它不会仅检索id,而是检索完整行并以急切的方式创建UserProfile,因为在任何情况下需要连接表时,获取附加数据几乎不需要任何内容​​。

Hibernate: one-to-one lazy loading, optional = false的答案表明,使关系不可选应该使它变得懒惰,但我怀疑它是真的。 Hibernate需要创建一个没有ID的代理,这在所有情况下都是正确的。失败的一种情况是当您从父实体中的集合中删除代理对象,然后尝试读取其数据时 - 因为代理本身没有携带足够的信息来懒惰地检索数据,所以如果没有父连接就不可能实体。

答案 1 :(得分:0)

这是正常的,默认情况下,hibernate会创建运行时代理。它将对象作为代理加载,除非指定了获取模式或设置为false。 例如,load()始终检索代理对象。如果在同一会话中多次调用,它将从持久性上下文缓存中读取数据。那是因为一旦对象被加载到缓存中,下一个后续调用就会执行可重复读取。