gpt4 book ai didi

java - 无法获取连接惰性初始化集合

转载 作者:行者123 更新时间:2023-11-30 05:25:22 26 4
gpt4 key购买 nike

由于 MultipleBagFetchException,我无法执行简单的 fetchjoin。

@Entity
public class Person {

@OneToMany(mappedBy="person",fetch=FetchType.LAZY)
private List<Auto> autos;
}


@Entity
public class Auto {

@ManyToOne
@JoinColumn(name = "person_id", nullable = false)
private Person person;

@OneToMany(mappedBy="auto",fetch=FetchType.LAZY)
private List<Tool> tools;

}

@Entity
@Table(name="tool")
public class Tool {

@ManyToOne
@JoinColumn(name = "auto_id", nullable = false)
private Auto auto;
}

如您所见,我的所有关联操作都使用默认的 fetchtype。

 @Query("SELECT p FROM Person p JOIN FETCH p.autos a JOIN FETCH a.tools")
List<Person>findAll();

结果:

Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.example.entities.Person.autos, com.example.entities.Auto.tools]

我已经阅读过有关此异常的信息,但在这些情况下,此异常的原因是对集合使用了 EAGER 获取类型。那这个呢?这是最简单的实体关系。

最重要的是,假设我们不被允许接触实体。如何仅在查询端解决这个问题?

最佳答案

有一种方法可以在不接触实体的情况下避免 n+1 查询,仅更改 findAll 的查询。我们可以编写一个包装函数,该函数将首先为人员加载汽车,然后他们在一次选择中获取所有工具。

人员存储库

    @Query("SELECT distinct p FROM Person p JOIN FETCH p.autos a")
List<Person> findAll();

包装代码

    List<Person> persons = personRepository.findAll();
Session session = (Session) entityManager.getDelegate();
List<Auto> autos = new ArrayList<>();
for (Person person : persons) {
if(!CollectionUtils.isEmpty(person.getAutos())) {
autos.addAll(person.getAutos());
}
}
try{
autos = session.createQuery("select distinct a from Auto a Join fetch a.tools " +
" where a in :autos", Auto.class)
.setParameter("autos", autos)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();
} catch (Exception ex) {
ex.printStackTrace();
}

第一个查询将是:

SELECT DISTINCT
person0_.id AS id1_6_0_,
autos1_.id AS id1_0_1_,
person0_.name AS name2_6_0_,
autos1_.name AS name2_0_1_,
autos1_.person_id AS person_i3_0_1_,
autos1_.person_id AS person_i3_0_0__,
autos1_.id AS id1_0_0__
FROM
Person person0_
INNER JOIN
Auto autos1_
ON
person0_.id=autos1_.person_id

生成的第二个查询将是:

    SELECT
auto0_.id AS id1_0_0_,
tools1_.id AS id1_8_1_,
auto0_.name AS name2_0_0_,
auto0_.person_id AS person_i3_0_0_,
tools1_.auto_id AS auto_id3_8_1_,
tools1_.name AS name2_8_1_,
tools1_.auto_id AS auto_id3_8_0__,
tools1_.id AS id1_8_0__
FROM
Auto auto0_
INNER JOIN
Tool tools1_
ON
auto0_.id=tools1_.auto_id
WHERE
auto0_.id IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

除此之外,我相信我们的选择是有限的,我们必须更改Tool实体FetchMode或为默认FetchMode.SELECT添加BatchSize,以便在单独的查询中获取Tools。

    @OneToMany(mappedBy = "auto", fetch = FetchType.LAZY)
@Fetch(FetchMode.SUBSELECT)
private List<Tool> tools;

查询将是

SELECT
tools0_.auto_id AS auto_id3_8_1_
, tools0_.id AS id1_8_1_
, tools0_.id AS id1_8_0_
, tools0_.auto_id AS auto_id3_8_0_
, tools0_.name AS name2_8_0_
FROM
Tool tools0_
WHERE
tools0_.auto_id IN
(
SELECT
autos1_.id
FROM
Person person0_
INNER JOIN
Auto autos1_
ON
person0_.id=autos1_.person_id
)

关于java - 无法获取连接惰性初始化集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58780851/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com