如果你从来没有遇到过著名LazyInitializationException, 那么你实际上没有真正使用Hibernate过:),但是,如果你遇到过,你是将LAZY懒加载切换到AGER立即加载,那么这里建议对你有用。
通常情况下,当我们遇到一个LazyInitializationException,我们倾向于修改关系抓取类型,将LAZY切换到EAGER,但这很不好!这是一种代码坏味道。避免此异常的最佳方法是依赖JOIN FETCH+ DTO(如果需要)。这里的应用程序是JOIN FETCH没有DTO 的示例(它在单个SELECT查询中获取实体)。点击DTO可以获得更多DTO案例。
关键点:
- 定义两个相关实体(例如,Category和Product之间有一对多的lazy双向关系)
@Entity public class Category implements Serializable {
private static final long serialVersionUID = 1L;
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Column(name = "category_name") private String cname;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "category", orphanRemoval = true) private List<Product> products = new ArrayList<>();
|
@Entity public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Column(name = "product_name") private String pname;
@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "category_id") private Category category;
|
- 编写一个JPQL JOIN FETCH来获取包含Product产品的类别Category
@Repository @Transactional(readOnly = true) public interface CategoryRepository extends JpaRepository<Category, Long> {
@Query(value = "SELECT c FROM Category c JOIN FETCH c.products WHERE c.cname = ?1") Category categoryIncludingProducts(String cname); }
|
- 编写一个JPQL JOIN FETCH来获取包括类别Category在内的所有产品Product
@Repository @Transactional(readOnly = true) public interface ProductRepository extends JpaRepository<Product, Long> { @Query(value = "SELECT p FROM Product p JOIN FETCH p.category") List<Product> productsIncludingCategory(); }
|
输出结果:
源代码可以在这里找到