【问题标题】:JPA Join on conditional result in N+1 problemJPA加入条件导致N+1问题
【发布时间】:2020-09-22 16:17:05
【问题描述】:

我面临多个选择查询 (N+1) 到 JOIN.ON 条件。这是我的例子

这是我在 Person 实体中的映射

    @ManyToOne(fetch = FetchType.EAGER)
    @Fetch(FetchMode.JOIN)
    @JoinColumns({
            @JoinColumn(name = "vehicleId", referencedColumnName = "vehicleId")
    })
    @WhereJoinTable( clause = "vehicle_color = 'RED' " ) - I did try this annotation but dont see conditional join in hibernate generated query
    private Vehicle vehicle;

所以我尝试使用 CriteriaBuilder

Join<Person, Car> vehicleJoin = personJoin.join("vehicle", JoinType.LEFT);
vehicleJoin.on(criteriaBuilder.isNotNull(personJoin.get(" vehicle_color = 'RED' ")))

一旦我添加了 vehicleJoin.on 条件,我确实看到它已正确连接,但它正在为该人的每辆汽车执行一个选择查询

我想避免多次选择并获取所有车辆数据作为主查询的一部分

这是在我的项目中使用的 jars

spring-boot-starter-data-jpa 2.1.6

休眠核心 5.3.10

提前感谢您的意见。希望它更容易阅读和理解:D

【问题讨论】:

    标签: hibernate jpa-2.0


    【解决方案1】:

    我想您正在编写实体查询?这实际上是不可能的,因为您必须使用带有 ON 条件的 fetch join。由于这会改变集合的持久状态,这可能会导致意外删除,因此 JPA 中不允许这样做。

    您需要一个元组查询,即自定义投影。

    这是Blaze-Persistence Entity Views 的完美用例。

    我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义模型之间轻松映射,例如 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例是拥有作为实体模型子集的 DTO。

    示例模型可能如下所示:

    @EntityView(Person.class)
    public interface PersonView {
        @IdMapping
        Integer getId();
        @Mapping("vehicle[color = 'RED']")
        VehicleView getVehicle();
    }
    @EntityView(Vehicle.class)
    public interface VehicleView {
        @IdMapping
        Integer getId();
        String getName();
    }
    

    查询是将实体视图应用于查询的问题,最简单的就是通过 id 进行查询。

    PersonView p = entityViewManager.find(entityManager, PersonView.class, id);

    Spring Data 集成让您可以像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features 即拥有类似于以下内容的存储库

    @Repository
    public interface PersonRepository {
        PersonView findById(Integer id);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-11-06
      • 2016-09-13
      • 2011-07-30
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 2013-10-13
      • 2020-08-21
      • 1970-01-01
      相关资源
      最近更新 更多