【问题标题】:Should I fetch join all the entities that are lazily loaded?我应该获取加入所有延迟加载的实体吗?
【发布时间】:2021-11-27 05:34:13
【问题描述】:

我目前正在使用 JPA 和 queryDSL 开发一个 Web 项目。

据我所知,fetch join 是用来减少执行延迟加载时发送给 DBMS 的 SQL 数量。 (因为 fetch 连接的实体包含在持久化上下文中)

如果是这样,是否应该使用 fetch join 调用所有延迟加载到服务层中的实体?

例如,有聊天系统的发帖社区...

聊天室桌。
ChatRoom (Long id, Member memberFrom, Member memberTo, Post post) 
// post is where the chat starts from. The members can start a chat from the post.

请求聊天室列表的API只需要加入memberFrom和memberTo的实体。所以从功能上看,下面的查询满足条件。

return query.select(chat)
        .from(chat)
        .innerJoin(chat.memberFrom, member).fetchJoin()
        .innerJoin(chat.memberTo, member).fetchJoin()
        .where(chat.memberFrom.email.eq(email).or(
               chat.memberTo.email.eq(email)))
        .fetch();

但是将返回的 DTO 还需要 post 和 message 实体,因此它们将被延迟加载到服务层中。在这种情况下,我是否也应该像下面这样获取加入消息和发布实体?

return query.select(chat)
        .from(chat)
        .innerJoin(chat.memberFrom, member).fetchJoin()
        .innerJoin(chat.memberTo, member).fetchJoin()
        .innerJoin(chat.messages, message1).fetchJoin()
        .innerJoin(chat.post, post).fetchJoin()
        .where(chat.memberFrom.email.eq(email).or(
               chat.memberTo.email.eq(email)))
        .fetch();

【问题讨论】:

    标签: jpa querydsl


    【解决方案1】:

    这完全取决于加入的关联是否被实际读取/使用。如果它们未使用,则可以将它们保留为未初始化,并且它们不会导致执行任何额外的 SQL 语句。相反,Hibernate 将代理这些字段。

    【讨论】:

    • 所以你的意思是如果使用连接的关联,总是首选使用 fetch join 而不是 join?
    • 这取决于关联的多样性和连接产品的复杂性。一对一的关系通常可以毫无问题地立即加载。必须预先加载可选的一对一关系。无论如何,不​​能在同一个查询中预先加载多对多关联。具有大表跨度(连接表、辅助表或表继承)的实体在连接时可能会产生如此复杂的查询,从而在单独获取关联时产生更快的查询计划。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    • 2010-10-25
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多