【问题标题】:Criteria API ignore LAZY fetchCriteria API 忽略 LAZY fetch
【发布时间】:2021-02-24 22:36:45
【问题描述】:

我有两个实体 CustomerProduct 具有一对多的关系,采用惰性策略。

问题是 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


【解决方案1】:

我猜你正在使用 Spring?尝试禁用spring.jpa.properties.hibernate.enable_lazy_load_no_trans,这无论如何都是反模式。

【讨论】:

    【解决方案2】:

    原因是EntityManager 举行公开会议。并按需加载子实体。在我的情况下.getProducts()

    关闭会话直接使用entityManager.close()

    【讨论】:

      猜你喜欢
      • 2021-03-02
      • 1970-01-01
      • 2015-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      • 1970-01-01
      • 2016-12-22
      相关资源
      最近更新 更多