SpringBoot JPA如何保存实体外键到EmployeeOfMonth关联表
问题根因
月度员工记录无法存入数据库有两个直接原因:
- 随机抽取到目标员工后,没有创建
EmployeeOfMonths实体对象,也没有调用Repository的保存方法执行持久化操作 EmployeeOfMonths实体类的@Table注解配置错误,表名和Employee表重复,会导致数据写入到错误的表中
修复方案
1. 修正实体类配置
先修改EmployeeOfMonths类的表名配置,给月度员工表指定独立表名,建议补充获奖月份字段,否则后续无法区分每条记录对应哪个月的评选结果:
@NoArgsConstructor @AllArgsConstructor @Data @Builder @Entity // 修正表名,原配置和Employee表重名 @Table(name = "employee_of_months") public class EmployeeOfMonths{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // 新增获奖月份字段,方便后续按月份查询记录 @Column(name = "award_month") @JsonFormat(pattern="yyyy-MM") private Date awardMonth; @ManyToOne @JoinColumn(name="employee_id", referencedColumnName="id") private Employee employee; }
2. 调整Service层逻辑,补充保存操作
先注入EmployeeOfMonthsRepository,在抽到随机员工后构建月度员工记录,调用save方法存入数据库,同时补充空判断避免员工表为空时出现下标越界错误:
@Autowired private EmployeeOfMonthsRepository employeeOfMonthsRepository; @Override public EmployeeDTO selectEmployee(Employee employee) { List<Employee> all = employeeRepository.findAll(); if (all.isEmpty()) { throw new RuntimeException("无有效员工数据,无法评选月度员工"); } Random randomizer = new Random(); Employee randomEmployee = all.get(randomizer.nextInt(all.size())); // 构建月度员工获奖记录 EmployeeOfMonths awardRecord = EmployeeOfMonths.builder() .employee(randomEmployee) .awardMonth(new Date()) .build(); // 执行保存 employeeOfMonthsRepository.save(awardRecord); return EmployeeMapper.toDto(randomEmployee); }
你在
Employee实体的employeeOfMonths字段配置了CascadeType.ALL级联规则,也可以选择把新建的awardRecord加到randomEmployee的employeeOfMonths集合中,再保存Employee对象,两种保存方式效果一致。
3. 修正Controller层冗余参数
当前接口是GET请求同时绑定了定时任务,不需要接收Employee类型的入参,直接去掉即可,避免参数绑定异常:
@Scheduled(cron = "0 15 10 15 * ?", zone = "Europe/Istanbul") @GetMapping(path="/month") public EmployeeDTO selectEmployee(){ return employeeService.selectEmployee(null); }
可选优化
- 如果需要限制员工不能连续当选,可以在抽取候选员工时,把近1-3个月已经获奖的员工ID过滤掉,再从剩余员工中随机抽取
- 定时任务要正常触发,需要在项目启动类上添加
@EnableScheduling注解 - 如果需要保证每个月只生成一条月度员工记录,可以在评选前先查询当前月份是否已经存在获奖记录,存在则直接返回已有结果,不需要重复抽取和保存
内容的提问来源于stack exchange,提问作者NewDeveloper
相关产品推荐
相关产品推荐

