寻找嵌套资源的练习
比方说,我有一个REST资源,如:
/公司/ {} companyId /部门/ {}的DepartmentID /员工/ {}雇员
以及CompanyEntity具有List<DepartementEntity>
且DepartmentEntity具有List<EmployeeEntity>
实体类。 所有ID都是唯一的。
所以现在有人在打电话
GET /companies/{companyId}/departments/{departmentId}/employees/{employeeId}
在Spring Data JPA / Hibernate中用{employeeId}查找雇员的好方法是什么?
办法:
employeeRepository.findOne(雇员);
专业版:只有1个查询
Contra:companyId和departmentId未使用。 他们甚至可以是随机的。 这是GET / employee / {id},但我想保留与公司和部门的嵌套资源。
此外,我想访问公司对象以检查询问的人是否与员工在同一家公司。
办法:
company = companyRepository.findOne(companyId);
for(DepartmentEntity department:company.getDepartments()){
if(department.getId() == departmentId) {
for(EmployeeEntity employee : department.getEmployees()) {
if(employee.getId() == employeeId)
return employee;
}
}
}
Pro:考虑companyId和departementId
Contra:如果使用延迟加载,许多查询
谢谢。
只要阅读这些问题和意见,几点:
更广泛地考虑JB Nizet的建议,我认为这个想法是使用最直接的查找,然后验证。 验证保护您的数据免受未经授权的访问,并确保关系查询语义保持不变。 即如果用户记录不在指定的部门中,则用户不会期望返回员工记录; 也不是该部门在指定公司内无效。
因此,为您提供一种简单的方式来获取员工的部门和部门的公司,这在您的实施中(而不一定在API中)是有意义的,因此您可以执行这些验证。 或者,每个容器都可以包含哈希ID集合,因此您可以轻松确定给定的员工ID是否在department.employees集合中,并且与company.departments中的部门相同。
这种情况并不罕见,而且这样做嵌套集合通常很有帮助。 关系端点是这个API设计模式的一个名称。 但是我同意Oliver Gierke的观点,你应该为用户提供一个直接通往已知实体的途径。 将这个因素分解到您的设计的不同方式:
/departments
和/employees
集合。 在嵌套资源返回的结果中,可以包含规范链接,如模式所示。 因此, GET /companies/123/departments/456/employees/789
可以返回员工的表示形式,以及canonical
链接(在标题或正文中,取决于您的有线格式)到/employees/789
,客户可以使用这用于随后访问员工记录。 GET /companies/{companyId}/departments
将超链接集合返回给公司内的部门; 每个超链接指向规范URL,例如/departments/456
。 不需要进一步的嵌套层次,因为员工以及您需要了解的关于部门的所有内容都可以通过规范资源获得。