java - 使用 hibernate/spring 一次加载所有惰性集合

标签 java spring hibernate spring-data-jpa

我有一个问题,加载惰性集合会产生大量 SQL 语句,我想知道是否没有更有效的方法来加载数据。

情况:

Parent 有一个名为 Children 的惰性集合 Child。它实际上是一个多对多的关系。

我使用 CrudRepository 加载一个Parent列表,并且我需要获取每个Parent的所有child_ids。因此,每次访问子集合时,我都会执行一个新的 SQL 语句。

如果我加载 200 个 parent ,则会执行 201 个查询(1 个用于 parent 列表,1 个用于每个 parent 的 child )。

知道如何仅通过一个查询加载数据吗?

编辑 1

“父/子”在这里可能是一个不好的命名。事实上,我有一个多对多关系。

这是一些代码:

@Entity
public class Tour {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name="system-uuid",
        strategy = "uuid2")
    @Column(length = 60)
    private String id;

    @ManyToMany
    @JoinTable(
        name="parent_images",
        joinColumns = @JoinColumn(name="tour_id", referencedColumnName = "id"),
        inverseJoinColumns = @JoinColumn(name="image_id", referencedColumnName = "id"),
        foreignKey = @ForeignKey(name = "FK_TOUR_IMAGE_TOUR"),
        inverseForeignKey = @ForeignKey(name = "FK_TOUR_IMAGE_IMAGE")
    )
    private List<Image> images = new ArrayList<>();
}

@Entity
public class Image {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name="system-uuid",
        strategy = "uuid2")
    @Column(length = 40)
    private String id;

    //....
}

// Code to fetch:
@Autowired
TourRepository repo;
List<Tour> tours = repo.findBy(....);


List<String> imageIds = new ArrayList<>();

for(Tour tour : tours){
    imageIds.addAll(tour.getImages().stream().map(b -> b.getId()).collect(Collectors.toList()));
}

最佳答案

正如另一个答案所建议的,JOIN FETCH通常是解决类似问题的方法。 join-fetch 内部发生的情况是,生成的 SQL 将包含 join-fetched 实体的列。

但是,您不应该盲目地将 join-fetch 视为万能药。

一种常见的情况是您想要检索具有 2 个一对多关系的实体。例如,您有用户,每个用户可能有多个地址电话

如果你天真地执行from User user join fetch user.phones join fetch users.addresses,Hibernate将报告你的查询中的问题,或者生成一个低效的查询,其中包含地址和地址的笛卡尔积电话。

在上述情况下,一种解决方案是将其分解为多个查询: from User user join fetch user.phones where .... 后跟 from User user join fetch user.addresses where ....

请记住:SQL 数量较少并不总是意味着性能更好。在某些情况下,分解查询可能会提高性能。

关于java - 使用 hibernate/spring 一次加载所有惰性集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45576330/

相关文章:

hibernate - 尝试锁定域对象时出现 StaleObjectStateException

java - Hibernate JPA,重复的子结果?

java - 为Java程序创建日志文件

java - primefaces 的数据模式不显示刷新数据形式的支持 bean

java - 如何让我的 Jersey 2 端点在启动时急切地初始化?

java - 无法滚动视频进度条|超文本标记语言

spring - 带有 Spring Integration 的 SOAP 代理

java - Spring Data - 无法捕获服务层中的 DataIntegrityViolationException

java - 如何在使用 ResourceBundle API 获取的属性文件中转义大括号

java - 如何读取具有可变数组深度和结构的复杂 JSON 字符串?