java - Spring Data JPA 实现一对一关系
问题描述
我正在尝试实现 Spring Data JPA 一对一的关系,但我遇到了问题。我有一张员工表和一张员工详细信息表。在员工表中,我有一个列employeeId,在表EmployeeDetail 中我有列employeeId。因此,当我向表中添加员工外键时,员工详细信息会自动增加。
这是我的实体:
Employee:
@OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
private EmployeeDetail employeeDetail;
EmployeeDetail:
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "employeeId")
private Employee employee;
这是我EmployeeServiceImpl
保存 Employee 的类和方法,也涉及到 EmployeeDetail。
public Employee saveEmployee(Employee employee) {
EmployeeDetail employeeDetail = employee.getEmployeeDetail();
employeeDetail.setEmployee(employee);
employee = employeeRepository.save(employee);
return employee;
}
在 EmployeeController 中,我有这两种方法来显示添加新员工和存储新员工的表单:
@GetMapping("/showFormForAdd")
public String showFormForAdd(Model theModel) {
// create model attribute to bind form data
Employee theEmployee = new Employee();
theModel.addAttribute("employee", theEmployee);
return "addNewEmployeeForm";
}
@RequestMapping(value = "/addNewEmployee",method = RequestMethod.POST)
@ResponseBody
public Employee addNewEmployee(@ModelAttribute("employee") @RequestBody Employee employee) {
Employee employeeResponse = employeeService.saveEmployee(employee);
return employeeResponse;
}
这只是.jsp
添加新员工表格的一部分:
<form:form action="addNewEmployee" modelAttribute="employee" method="POST">
如您所见,我的模型属性在我的文件中以表格形式存在employee
,但无法识别。.jsp
我可以通过什么方式修复它?那么当我创建新员工时,他的 ID 会自动存储在 EmployeeDetail 中吗?或者我如何将数据添加到我的相关表(EmployeeDetail)?
解决方案
我不知道如何在保存员工时将员工 ID 直接存储在详细信息表中,但我会做的是
- 创建一个员工表单,通过员工控制器处理它,如下所示
@GetMapping("/add")
public String handleEmployeeForm(Model model) {
model.addAttribute("employee", new Employee());
return "formEmployee";
}
@PostMapping("/add")
public String saveEmployee(@ModelAttribute("employee") Employee employee, Errors errors) {
if(errors.hasErrors()) {
return "formEmployee";
}
this.employeeService.save(employee);
return "redirect:/employee/list";
}
@GetMapping("/list")
public String listEmployees(Model model) {
model.addAttribute("employees", this.employeeService.findAll());
return "listEmployee";
}
- 提供链接以添加员工的员工详细信息。我通过一个列出所有员工的页面来做到这一点(检查 EmployeeController 的 /employee/list API)。
<a th:href="@{/employeeDetails/add/{employeeId}(employeeId=${employee.id})}"
th:each="employee : ${employees}"><span th:text="${employee.employeeEmail}"></span></a>
- 创建一个员工详细信息表单,将员工 ID 存储为表单中的隐藏字段,通过员工详细信息控制器进行处理,如下所示。
<input type="hidden"
class="form-control" th:field="*{employee.id}"/>
员工详细信息控制器
@GetMapping("/add/{employeeID}")
public String handleEmployeeDetailsForm(@PathVariable long employeeID, Model model) {
//create dummy employee
Employee employee = new Employee();
//set id received from request to this employee object
employee.setId(employeeID);
EmployeeDetails employeeDetails = new EmployeeDetails();
//set dummy employee object
employeeDetails.setEmployee(employee);
model.addAttribute("employeeDetails", employeeDetails);
return "formEmployeeDetails";
}
@PostMapping("/add")
public String saveEmployeeDetails(@ModelAttribute EmployeeDetails employeeDetails, Errors errors) {
if(errors.hasErrors()) {
return "formEmployeeDetails";
}
//fetch actual employee object from database
Employee employee = this.employeeService.findById(employeeDetails.getEmployee().getId());
//set to employee details object
employeeDetails.setEmployee(employee);
//save employee details object
this.employeeDetailsService.save(employeeDetails);
return "redirect:/listEmployeeDetails";
}
编辑 1
实现预期结果的另一种方法是修改员工和员工详细信息类,如下面的
员工
@OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private EmployeeDetail employeeDetail;
@PrimaryKeyJoinColumn 注释告诉 Employee 的主键将用作 EmployeeDetails 中的外键。
EmployeeDetail
@OneToOne
@MapsId
private Employee employee;
您将在此处保存 EmployeeDetails 作为其拥有方(我们在 Employee 中定义了 mappedBy),它将包含对 Employee 的外键引用。
EmployeeDetailsController
@GetMapping("/add")
public String handleEmployeeForm(Model model) {
EmployeeDetails employeeDetails = new EmplyeeDetails();
employeeDetails .setEmployee(new Employee());
model.addAttribute("employeeDetails", employeeDetails );
return "formEmployee";
}
@PostMapping("/add")
public String saveEmployee(@ModelAttribute("employeeDetails") EmployeeDetails employeeDetails) {
this.employeeDetailsService.save(employeeDetails);
return "redirect:/employee/add";
}
推荐阅读
- ios - UITextField 控件丢失委托引用 ID
- python - 我想合并 2 个 xlsx 数据框 - 匹配并将数据复制到多行
- html - 网站上的图像未在 iOS 设备上显示
- javascript - 检查对象数组以查找双精度
- javascript - Dynamics CRM - 从子网格创建记录时的 N:N 关系数据/字段/属性映射
- css - 使用mr或ml时如何在Bootstrap网格中填充一行?
- python - Python 并行化 For 循环以提取图像并写入文件
- python - SQL 新手只是试图导入 SQL 转储以在 python 中使用,不断收到“缺少数据库”和“缺少列”错误
- spring - 只有一个标头的 Spring Request 映射问题
- c++ - C++中将数字转换为向量数组的函数