Spring中Worker与Speciality多对多关联POST请求实现方案咨询
实现步骤
第一步:修正实体类关联配置错误
现有代码存在两处配置错误会导致关联异常,优先修正:
- Speciality类的多对多关联
mappedBy属性配置错误,mappedBy需填写对方实体类中关联属性的名称,而非数据库字段名:
// 修正前 @ManyToMany(mappedBy = "speciality_id") private Set<Worker> workers = new HashSet<>(); // 修正后 @ManyToMany(mappedBy = "specialities") @JsonIgnore // 新增该注解避免序列化Worker时出现循环引用问题 private Set<Worker> workers = new HashSet<>();
- Worker类的多对多级联配置移除
CascadeType.PERSIST,避免误触发Speciality的新增逻辑:
// 修正前 @ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST }) // 修正后 @ManyToMany(cascade = CascadeType.MERGE)
第二步:Controller层调整逻辑
首先在WorkerController中注入SpecialityRepository,后续用于查询已存在的Speciality实例,不直接使用前端传入的Speciality对象,避免非法修改Speciality数据。
修改后的POST接口代码如下:
@RestController @RequestMapping("/api") public class WorkerController { @Autowired private WorkerRepository workerRepository; // 新增注入SpecialityRepository @Autowired private SpecialityRepository specialityRepository; @PostMapping("/worker") public ResponseEntity<Worker> createWorker(@RequestBody Worker worker) { try { // 处理关联的Speciality:只关联数据库已存在的记录 Set<Speciality> existSpecialities = new HashSet<>(); for (Speciality reqSpeciality : worker.getSpecialities()) { // 方式1:用getReferenceById直接获取代理对象,无需查询数据库,适合确定SpecialityId一定存在的场景 Speciality existSpeciality = specialityRepository.getReferenceById(reqSpeciality.getSpeciality_id()); // 方式2:如果需要校验Speciality是否存在,改用findById,不存在直接返回参数错误 // Optional<Speciality> specialityOpt = specialityRepository.findById(reqSpeciality.getSpeciality_id()); // if (specialityOpt.isEmpty()) { // return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); // } // Speciality existSpeciality = specialityOpt.get(); existSpecialities.add(existSpeciality); } // 构建要保存的Worker对象 Worker _worker = new Worker( worker.getName(), worker.getSurname(), worker.getEmail(), worker.getPhoneNumber(), existSpecialities, // 替换为查询到的已存在Speciality集合 worker.getCollege(), worker.getFaculty() ); workerRepository.save(_worker); return new ResponseEntity<>(_worker, HttpStatus.CREATED); } catch (Exception e) { e.printStackTrace(); return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR); } } }
前端请求示例
前端调用接口时,specialities字段只需要传每个已选Speciality的speciality_id即可,无需传其他Speciality属性,请求JSON示例:
{ "name": "张三", "surname": "张", "email": "zhangsan@xxx.com", "phoneNumber": "13xxxxxxxxx", "specialities": [ {"speciality_id": 1}, {"speciality_id": 3} ], "college": {"college_id": 2}, "faculty": {"faculty_id": 5} }
内容的提问来源于stack exchange,提问作者Bartek
相关产品推荐
相关产品推荐

