【发布时间】:2021-02-24 22:36:45
【问题描述】:
我有两个实体 Customer 和 Product 具有一对多的关系,采用惰性策略。
问题是 fetch 不是惰性的,products 集合总是会获取所有相关的产品。
public Optional<Customer> findById(final long customerId) {
final EntityManager entityManager = sessionFactory.createEntityManager();
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Customer> criteriaQuery = criteriaBuilder.createQuery(Customer.class);
final Root<Customer> customerMetamodel = criteriaQuery.from(Customer.class);
criteriaQuery.where(criteriaBuilder.equal(customerMetamodel.get("id"), customerId));
final TypedQuery<Customer> query = entityManager.createQuery(criteriaQuery);
return Optional.ofNullable(query.getSingleResult());
}
你可以看到没有人提到 fetch eager,在实体类中同样如此,都是惰性的:
客户
@Data
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "customer")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
@OneToMany(mappedBy = "customer", fetch = FetchType.LAZY)
private List<Product> products;
}
产品
@Entity
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@ToString(exclude = "customer")
@Table(name = "product")
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private BigDecimal price;
@ManyToOne(fetch = FetchType.LAZY)
private Customer customer;
}
为什么惰性工作如此渴望以及在这种情况下如何启用真正的惰性模式?
UPDATE_1
与 H2 的集成测试
@Test
public void testFindById() {
Customer customer = customerRepository.create(Customer.builder().age(20).name("Denis").build());
productRepository.create(Product.builder().customer(customer).price(new BigDecimal(100)).build());
productRepository.create(Product.builder().customer(customer).price(new BigDecimal(200)).build());
productRepository.create(Product.builder().customer(customer).price(new BigDecimal(300)).build());
final Customer result = customerRepository.findById(customer.getId()).orElseThrow();
assertEquals("Denis", result.getName());
assertThrows(LazyInitializationException.class, () -> System.out.println(result.getProducts()));
}
我打电话给.getProducts(),但期待LazyInitializationException,因为会话已经关闭。
【问题讨论】:
-
"产品集合总是获取所有相关产品" - 你确定吗?你是怎么检查的?我希望不是通过调用 getProducts - 因为这实际上会触发延迟加载。
-
@mvmn 谢谢你的关注,我是更新问题。
标签: java hibernate criteria hibernate-criteria criteria-api