你正在得到LazyInitializationException
因为您正在访问事务上下文之外的书籍内容,很可能是因为它已经关闭。例子:
您可以在 Service 类的方法中使用 DAO 或 Spring Data 存储库从数据库获取 Owner:
public Owner getOwner(Integer id) {
Owner owner = ownerRepository.findOne(id);
// You try to access the Set here
return owner;
}
此时,您有一个 Owner 对象,其中有一个为空的 books Set,并且仅当有人想要访问其内容时才会填充。仅当存在未完成的交易时才能填充账本集。不幸的是,findOne
方法已经打开并且已经关闭了交易,所以没有打开的交易,你会得到臭名昭著的LazyInitializationException
当你做类似的事情时owner.getBooks().size()
.
您有几个选择:
使用@Transactional
正如 OndrejM 所说,您需要以在同一事务中执行的方式包装代码。最简单的方法是使用 Spring 的@事务性 https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html注解:
@Transactional
public Owner getOwner(Integer id) {
Owner owner = ownerRepository.findOne(id);
// You can access owner.getBooks() content here because the transaction is still open
return owner;
}
使用 fetch = FetchType.EAGER
你有fetch = FecthType.LAZY
in you @Column
定义,这就是为什么 Set 被延迟加载(如果没有指定,这也是 JPA 默认使用的获取类型)。如果您希望在从数据库获取 Owner 对象后立即自动完全填充 Set,您应该像这样定义它:
@OneToMany(fetch = FetchType.EAGER, mappedBy = "owner")
private Set<Book> books= new HashSet<Book>();
If the Book
实体不是很重并且每个Owner
没有大量的书籍,从数据库中取出该所有者的所有书籍并不是犯罪。但您还应该注意,如果您检索以下列表Owner
您也从所有这些所有者那里检索所有书籍,并且Book
实体也可能正在加载它所依赖的其他对象。