0

我想询问 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=?
4

2 回答 2

1

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

您的查询应该是这样的:

@Query("FROM account a LEFT JOIN FETCH a.roles r WHERE a.username = :username")
于 2021-05-22T13:09:42.740 回答
0

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

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

于 2021-05-21T08:35:24.817 回答