2.1 获取选项
Hibernate 的开发人员很早就知道加载子实体的问题。所以他们做的第一件事就是在注释中添加一个特殊的提取@OneToMany
参数,@ManyToMany
。
该参数可以取两个值:
- 渴望的
- 懒惰的
例子:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
如果fetch 参数等于 EAGER,那么当加载父实体时,它的所有子实体也将被加载。此外,Hibernate 将尝试在一个 SQL 查询中执行此操作,生成大量查询并一次获取所有数据。
如果fetch 参数取值为 LAZY,那么在加载父实体时,不会加载子实体。相反,将创建一个代理对象。
借助这个代理对象,Hibernate 会跟踪对这个子实体的访问,并在第一次访问时将其加载到内存中。
如果我们回顾我们的情况并发表评论:
@Entity @Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "user_id")
public List<Comment> comments;
}
然后你有一个“别致的选择”:
如果fetch = FetchType.EAGER
,那么 Hibernate 将在第一行代码加载所有注释:
User user = session.get(User.class, 1); //load all comments here
List<Comment> comments = user.getComments();
如果fetch = FetchType.LAZY
,那么 Hibernate 将在第 2 行代码加载所有注释:
User user = session.get(User.class, 1);
List<Comment> comments = user.getComments(); //load all comments here
正如您已经猜到的那样,当它没有加载所有评论时,您别无选择 :)
2.2 默认值
如果您没有为@ManyTo
... 注释指定提取选项,那么 Hibernate 将使用默认值。
对于不同的注释类型,它们略有不同。对于注解@OneToOne
是@ManyToOne
EAGER,对于注解@OneToMany
是@ManyToMany
LAZY。很容易记住——如果我们引用一个对象,那么它将被完全加载。如果我们引用一个集合,那么它将在第一次访问时加载。
2.3 @LazyCollection注解
正如您已经看到的,fetch 参数在处理集合时没有多大帮助。Hibernate 的创建者试图通过添加一个特殊的注解来解决这个问题@LazyCollection
。通常是这样写的:
@LazyCollection(LazyCollectionOption.TRUE)
映射集合字段时需要指定:
@Entity @Table(name="user")
class User {
@Column(name="id")
public Integer id;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
public List<Comment> comments;
}
此注解有一个值参数,可以采用以下三个值之一:
- 惰性集合选项。真的
- 惰性集合选项。错误的
- 惰性集合选项。额外的
前两个选项与 fetch 选项非常相似。
如果参数设置为LazyCollectionOption.TRUE
,则表示在加载父User对象时,不会从数据库中加载comments字段的值。Comment 类型的对象将在第一次访问 comments 字段时加载。其实这个相当于参数FetchType.LAZY
如果参数设置为LazyCollectionOption.FALSE
,则表示comments字段的值会在加载父User对象时从数据库中加载。Comment 类型的对象将在第一次访问 comments 字段时加载。事实上,这相当于FetchType.EAGER
.
GO TO FULL VERSION