【问题标题】:LEFT JOIN FETCH not solving n+1 issueLEFT JOIN FETCH 不能解决 n+1 问题
【发布时间】:2021-08-10 09:35:28
【问题描述】:

我想询问 N+1 问题的解决方案。我有具有 1:M 关系的 Account 表和 Account_role 表。我通过在@Query 中使用 LEFT JOIN FETCH 尝试连接获取方法,但不起作用。

帐户类别:

@Entity(name = "account")
@Table(name = "account")
public class AccountBean implements Serializable {
    @Id
    @Column("username")
    private String username

    @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "username", referencedColumnName = "username", insertable = false, updatable = false)
    private Set<AccountRoleBean> roles = new HashSet<>();

    // getters setters
}

帐户角色类:

@Entity(name = "account_role")
@Table(name = "account_role")
public class AccountRoleBean implements Serializable {

    @Id
    @Column(name = "id")
    private Integer id;

    @Column(name = "username")
    private String username;

    // getters setters
}

帐户存储库类

public interface AccountRepo extends JpaRepository<AccountBean, String> {
    @Query("FROM account a LEFT JOIN FETCH account_role role ON a.username = role.username WHERE a.username = :username")
    AccountBean findAccountWithRoles(String username);
}

输出

Hibernate: 
    select
        accountbea0_.username as username1_0_0_,
        accountrol1_.id as id1_1_1_,
        accountbea0_.is_active as is_activ2_0_0_,
        accountbea0_.last_login_date as last_log3_0_0_,
        accountbea0_.pw as pw4_0_0_,
        accountrol1_.username as username3_1_1_,
        accountrol1_.role_name as role_nam2_1_1_ 
    from
        account accountbea0_ 
    left outer join
        account_role accountrol1_ 
            on (
                accountbea0_.username=accountrol1_.username
            ) 
    where
        accountbea0_.username=?
Hibernate: 
    select
        roles0_.username as username3_1_0_,
        roles0_.id as id1_1_0_,
        roles0_.id as id1_1_1_,
        roles0_.username as username3_1_1_,
        roles0_.role_name as role_nam2_1_1_ 
    from
        account_role roles0_ 
    where
        roles0_.username=?

【问题讨论】:

    标签: mysql hibernate jpa spring-data-jpa select-n-plus-1


    【解决方案1】:

    使用 JPQL,您无需指定要连接的连接表和列,因为您已经在实体中完成了这些操作。

    您的查询应该是这样的:

    @Query("FROM account a LEFT JOIN FETCH a.roles r WHERE a.username = :username")
    

    【讨论】:

      【解决方案2】:

      更好的解决方案是使用名称实体图。 Entity graphs 定义急切获取哪些字段,您可以为多个查询重用相同的图,甚至是 Spring Data 从存储库方法名称自动推断的查询。您可以在您的 AccountBean 实体之上定义一个 named entity graph,您可以在其中指定 @NamedAttributeNode("roles"),因为您希望它急切地获取。然后你会做类似的事情

      accountRepo.findByName(myName, EntityGraph.EntityGraphType.LOAD, "theNameOfYourCustomEntityGraph");

      【讨论】:

        猜你喜欢
        • 2015-07-03
        • 1970-01-01
        • 2015-02-12
        • 2018-11-01
        • 2011-10-13
        • 1970-01-01
        • 1970-01-01
        • 2011-02-05
        • 1970-01-01
        相关资源
        最近更新 更多