【问题标题】:Spring Data JPA Implementation one to one relationshipSpring Data JPA 实现一对一关系
【发布时间】:2021-10-05 14:53:27
【问题描述】:

我正在尝试实现 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)?

【问题讨论】:

    标签: java spring jpa


    【解决方案1】:

    我不知道如何在保存员工时将员工 ID 直接存储在详细信息表中,但我会做的是

    1. 创建一个员工表单,通过员工控制器处理它,如下所示
        @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";
        }
    
    
    1. 提供链接以添加员工的员工详细信息。我通过一个列出所有员工的页面来做到这一点(检查 EmployeeController 的 /employee/list API)。
    <a th:href="@{/employeeDetails/add/{employeeId}(employeeId=${employee.id})}" 
        th:each="employee : ${employees}"><span th:text="${employee.employeeEmail}"></span></a>
    
    1. 创建员工详细信息表单,将员工 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";
        }
    

    【讨论】:

    • 答案需要某种代码sn-ps
    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    • @BirhanNega Done.. 使用代码 sn-p 更新评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 2017-08-19
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多