You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环两个列表创建EmployeeProject时避免重复或值覆盖的方法

解决EmployeeProject关联保存的循环问题

问题根源分析

你遇到的两个问题本质是两个常见错误:

  1. 所有工时都是最后一个值:循环中复用了同一个EmployeeProject对象,后续赋值覆盖了之前的所有实例数据
  2. 生成重复数据(9条):对Project列表和Double列表做了嵌套循环,产生笛卡尔积(3×3=9),而非一一对应关联

一、修正Thymeleaf表单参数绑定

确保项目与对应工时通过索引绑定,提交后能按顺序匹配:

<!-- 遍历Project列表,为每个项目绑定对应工时输入框 -->
<div th:each="project, stat : ${projectList}">
  <!-- 隐藏字段存项目ID,按索引分组 -->
  <input type="hidden" th:name="projectIds[__${stat.index}__]" th:value="${project.id}" />
  <!-- 工时输入框,与对应项目索引一致 -->
  <input type="number" th:name="bookedMonths[__${stat.index}__]" step="0.1" placeholder="输入工时" />
</div>
<!-- 员工ID隐藏字段 -->
<input type="hidden" name="employeeId" th:value="${employee.id}" />

二、Controller正确处理逻辑

按索引一一遍历项目与工时,每次循环新建EmployeeProject实例,避免复用覆盖:

@PostMapping("/save-association")
public String saveEmployeeProject(@RequestParam Long employeeId,
                                  @RequestParam List<Long> projectIds,
                                  @RequestParam List<Double> bookedMonths) {
    // 获取关联员工
    Employee employee = employeeRepo.findById(employeeId).orElseThrow(() -> new RuntimeException("员工不存在"));
    
    // 按索引一一匹配项目与工时,避免笛卡尔积
    for (int i = 0; i < projectIds.size(); i++) {
        // 关键:每次循环新建实例,禁止复用
        EmployeeProject empProject = new EmployeeProject();
        
        // 设置关联员工
        empProject.setEmployee(employee);
        // 设置对应索引的项目
        Project project = projectRepo.findById(projectIds.get(i)).orElseThrow(() -> new RuntimeException("项目不存在"));
        empProject.setProject(project);
        // 设置对应索引的工时
        empProject.setEmployeeBookedMonths(bookedMonths.get(i));
        
        // 验证打印(此时输出应为正确值)
        System.out.println("项目:" + project.getName() + " | 工时:" + bookedMonths.get(i));
        
        // 持久化当前实例
        empProjectRepo.save(empProject);
    }
    
    return "redirect:/success";
}

三、实体类配置注意事项

确保EmployeeProject为独立实体,关联关系配置正确:

@Entity
@Table(name = "employee_project")
public class EmployeeProject {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "employee_id", nullable = false)
    private Employee employee;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "project_id", nullable = false)
    private Project project;
    
    @Column(name = "booked_months")
    private Double employeeBookedMonths;
    
    // 无参/全参构造函数、getter/setter
}
  • 避免在关联关系中配置错误的级联操作(如cascade = CascadeType.ALL),防止意外重复保存
  • 确保每个EmployeeProject实例都是独立对象,不要在循环外提前创建

四、调试验证

如果仍有问题,可在保存前打印实例哈希值,确认每次循环都是新对象:

System.out.println("实例哈希:" + empProject.hashCode() + " | 工时:" + empProject.getEmployeeBookedMonths());

若哈希值重复,说明仍在复用同一个EmployeeProject对象,需修正循环内实例化逻辑。

内容的提问来源于stack exchange,提问作者Kayd Anderson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:55:22