Java 在这种情况下是否可以避免N+1请求?

Java 在这种情况下是否可以避免N+1请求?,java,sql,jpa,Java,Sql,Jpa,我有以下班级模式: 我是这样实施的: 项目: @Data public class Project { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @ManyToMany @JsonIgnore @JoinTable( name = "employee_projects", joinColumns = @JoinColumn(name

我有以下班级模式:

我是这样实施的:

项目:

@Data
public class Project {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  @ManyToMany
  @JsonIgnore
  @JoinTable(
          name = "employee_projects",
          joinColumns = @JoinColumn(name = "project_id"),
          inverseJoinColumns = @JoinColumn(name = "employee_id")
  )
  private List<Employee> employees;

  @OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true)
  private List<Role> roles;

  // more fields
}
Im目前只能在n+1个请求中实现这一点:

一个查找项目所有员工的请求:

@Query("SELECT project.employees FROM Project project WHERE project.id = :id")
List<Employee> findByProjectId(@Param("id") long id)

我能在一个请求中实现这一点吗?如果没有,我的其他选择是什么,我应该尝试重新构建类图吗?

我不知道我是否正确理解这一点,也不知道您是否搜索更多的hibernate解决方案或SQL解决方案,但我认为这会行得通:

SELECT
    p.employees

FROM project p

INNER JOIN employee e
    ON e.project.id = p.id      -- this ensure to get all emps from the selected project

LEFT JOIN role r                -- left join ensure to keep all records from employee, even if he hasn't a role
    ON  r.project.id = p.id     -- this ensure to get all role from the selected project
    AND r.employee.id = e.id    -- and linked to a employee too

WHERE
    p.id = :id

这是基于您的疑问句。

是的,这可以在单个查询中完成。您的查询将如下所示-

@Query(value = "select employee, role " +
            "from Employee as employee " +
            "inner join Project as project on employee member of project.employees " +
            "inner join Role as role on project = role.project and employee member of role.employees " +
            "where " +
            "  project.id = :projectId")
List<Tuple> getEmployeeRoles(Long projectId);
您可以在jpa查询中使用clas构造函数返回更漂亮的列表


干杯

为什么在项目JavaBean上执行查询而不是调用getEmployes?我知道,不知道为什么在这里编写查询。但不管怎么说,这都是一样的,因为员工们都是懒散的。你需要做的第一件事就是修复你的映射。双向关联的一侧必须是相反的一侧。阅读
@Query("SELECT project.employees FROM Project project WHERE project.id = :id")
List<Employee> findByProjectId(@Param("id") long id)
@Query("SELECT role FROM Role role WHERE role.project.id = :projectId AND :employeeId IN (SELECT employees.id FROM role.employees employees)
Role findByProjectIdAndEmployeeId(@Param("projectId") long projectId, @Param("employeeId") long employeeId)
SELECT
    p.employees

FROM project p

INNER JOIN employee e
    ON e.project.id = p.id      -- this ensure to get all emps from the selected project

LEFT JOIN role r                -- left join ensure to keep all records from employee, even if he hasn't a role
    ON  r.project.id = p.id     -- this ensure to get all role from the selected project
    AND r.employee.id = e.id    -- and linked to a employee too

WHERE
    p.id = :id
@Query(value = "select employee, role " +
            "from Employee as employee " +
            "inner join Project as project on employee member of project.employees " +
            "inner join Role as role on project = role.project and employee member of role.employees " +
            "where " +
            "  project.id = :projectId")
List<Tuple> getEmployeeRoles(Long projectId);