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);