假设我们有以下三个域模型实体:Company
,Departament
和Employee
。
@Getter @Setter @NoArgsConstrutor
public class Employee {
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id", nullable = false, insertable = false, updatable = false)
private Department department;
@JoinColumn(name = "department_id", nullable = false)
private int department_id;
}
@Getter @Setter @NoArgsConstrutor
public class Department {
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "company_id", nullable = false, insertable = false, updatable = false)
private Company company;
@JoinColumn(name = "company_id", nullable = false)
private int company_id;
@OneToMany(mappedBy = "department")
private List<Employee> employees;
}
@Getter @Setter @NoArgsConstrutor
private class Company {
private String name;
@OneToMany(mappedBy = "company")
private List<Department> departments;
}
对于每个实体,我们都有Repositories
,它们扩展了JpaRepository
,Services
和Controllers
。在每个Service
中,我们分别@Autowire
Repository
,在每个实体Controller
中,我们从实体Service
调用方法。
我的问题是以下:我无法保存整个Company
,因为Departments
需要一个Company
ID,而Employees
Deparment
的ID。因此,首先,在我的CompanyService
中保存,然后清除departments
列表,执行一个saveAndFlush
,该ID为我的company
分配ID。我将接收到的ID分配给先前保存的company_id
列表的每个实体中的每个departments
,然后将列表附加回company
并执行另一个saveAndFlush
, employee
列表再花一次。
@RestController
public class CompanyController {
@Autowire
private CompanyService companyService;
@PostMapping("/companies")
public Company createCompany(@RequestBody Company newCompany) {
return companyService.createCompany(newCompany);
}
}
@Service
public class CompanyService {
@Autowire
private CompanyRepository companyRepository;
public Company createCompany(Company company) {
List<Department> departments = new ArrayList<>(company.getDepartments());
company.getDepartments().clear();
companyRepository.saveAndFlush(company);
int company_id = company.getId();
departments.forEach (department ->
department.setCompany_id(company_id);
);
//here I save a copy of the previously saved departments, because I still need the employees
company.getDepartments().addAll(departments.stream().map(department -> department.clone(department)).collect(Collectors.toList()));
company.getDepartments().forEach(department -> department.getEmployees().clear());
companyRepository.saveAndFlush(company);
//here I assign each employee it's corresponding department ID
for (int i = 0; i < company.getDepartments().size(); i++) {
Department departmentInSavedCompany = company.getDepartments().get(i);
Department departmentWhichStillHasEmployees = departments.get(i);
departmentWhichStillHasEmployees.setId(departmentInSavedCompany.getId());
departmentWhichStillHasEmployees.getEmployees().forEach(employee -> employee.setDepartment_id(departmentInSavedCompany.getId()));
}
company.getDepartments.clear();
company.getDepartments.addAll(departments);
return companyRepository.saveAndFlush(company);
}
}
@Repository
public interface CompanyRepository extends JpaRepository<Company, Integer> {
}
我目前不喜欢这种实现方式,我也不认为它很好。对于这种情况哪种方法是正确的?
答案 0 :(得分:1)
使用JPA时,请勿使用ID,而应使用对象引用。
在您的情况下,这意味着删除重复引用的id属性。
为了获得正确的ID实体,请使用JpaRepository.getOne
。如果实体已经在第一级缓存中,它将返回该实体,或者返回仅包装ID的代理,这样它将不会访问数据库。
这使您可以组装对象图并将其持久化,从没有引用其他实体的实体开始。
如果您将实体视为同一聚合的一部分,也可以考虑配置级联,即应将它们加载并持久保存在一起。