在N+1问题中,JPA在条件结果上的连接。

问题描述 投票:0回答:1

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

这是我的映射 人物 实体

    @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条件后,我确实看到它正确地加入了,但它正在为该人的每一辆车执行select查询。

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

下面是在我的项目中使用的罐子

spring-boot-starter-data-jpa 2.1.6

Hibernate-core 5.3.10

先谢谢大家的意见。希望能更容易阅读和理解 :D

hibernate jpa-2.0
1个回答
0
投票

我想你是在写一个实体查询?这其实是不可能的,因为你必须使用一个带有ON条件的fetch join。因为这将改变集合的持久化状态,可能会导致意外的删除,在JPA中是不允许的。

你需要一个元组查询来代替,即一个自定义的投影。

这是一个完美的用例 Blaze-持久性实体视图.

我创建这个库的目的是为了让JPA模型和自定义接口或抽象类定义的模型之间能够轻松地进行映射,就像Spring Data Projections一样。这个想法是,你以你喜欢的方式定义你的目标结构(领域模型),并通过JPQL表达式将属性(getters)映射到实体模型。由于属性名被用作默认映射,你大多不需要显式映射,因为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.comdocumentationentity-viewmanualen_USindex.html#spring-data-features。 即有一个类似于以下的仓库

@Repository
public interface PersonRepository {
    PersonView findById(Integer id);
}
© www.soinside.com 2019 - 2024. All rights reserved.