我想在Spring Data JPA中结合合并@ JuttyGraph和Specification来生成一个JOIN子句,而不是单独的JOIN子句。
@Entity
public class LoginUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String name;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private List<Role> roleList;
}
@Entity
public class Role {
@Id
private Integer id;
@Column(nullable = false)
private String name;
}
public interface LoginUserRepository extends JpaRepository<LoginUser, String>,
JpaSpecificationExecutor<LoginUser> {
@EntityGraph(attributePaths = {"roleList"})
public Page<LoginUser> findAll(Specification<LoginUser> spec, Pageable pageable);
}
public class LoginUserSpecification {
static public Specification<LoginUser> equalsRole(String role) {
return (root, query, builder) -> builder.equal(
root.join("roleList", JoinType.LEFT).get("name"), role);
}
}
public class LoginUserDetailsService {
public Page<LoginUser> getAccounts(Pageable pageable, UserSearchForm form) {
return loginUserRepository.findAll(
Specification.where(LoginUserSpecification.equalsRole(form.getRole())),
pageable);
}
}
生成的SQL:
select
l1_0.id,
l1_0.name,
r2_0.user_id,
r2_1.id,
r2_1.name
from
login_user l1_0
left
join ( /* JOIN clause generated by Specification */
user_role r1_0
join roles r1_1 on r1_1.id = r1_0.role_id
)
on l1_0.id = r1_0.user_id
left
join ( /* JOIN clause generated by @EntityGraph */
user_role r2_0
join roles r2_1 on r2_1.id = r2_0.role_id
)
on l1_0.id = r2_0.user_id
where
r1_1.name = 'ROLE_ADMIN'
预期SQL:
select
l1_0.id,
l1_0.name,
r2_0.user_id,
r2_1.id,
r2_1.name
from
login_user l1_0
left
join ( /* JOIN clause generated by @EntityGraph */
user_role r2_0
join roles r2_1 on r2_1.id = r2_0.role_id
)
on l1_0.id = r2_0.user_id
where
r2_1.name = 'ROLE_ADMIN'
是否有可能将重复的JOIN子句合并为一个如上所述的单独子句?
root.join("roleList", JoinType.LFET).get("name"), role);
理想情况下,在指定搜索条件时,JoinType.INNER是合适的。但是,我选择了LEFT,希望它可以优化查询。
1条答案
按热度按时间pdkcd3nj1#
我找不到一个方法来做到这一点,所以我改变了SQL和处理它。具体来说,我将规范更改为exists子句。