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

一对多映射外键未更新:员工技能多选表单关联问题

问题描述

我开发了一款员工表单,员工可通过下拉框选择多项技能,点击提交按钮后表单需完成保存,同时在formskills关联表中记录formid与skillid的映射关系,但目前无法实现该映射,尝试多种在线方案均无效。

  • 技能下拉框:前端展示的多选技能下拉组件,支持用户勾选多个技能选项
  • 前端请求载荷:提交表单时发送的请求体数据,包含表单基本信息及选中的技能列表
数据库表结构
  • FormTable(表单表):存储员工表单基本信息,包含formid(主键)、姓名、邮箱、手机号等字段
  • SkillTable(技能表):存储所有可选技能,包含skill_id(主键)、skill_name(技能名称)字段
  • FormSkills Table(表单技能关联表):关联表单与技能的中间表,包含formid(外键关联FormTable)、skillid(外键关联SkillTable)两个字段,用于记录表单对应的技能映射关系
后端实体代码

FormModel(表单实体)

@Entity
@Table(name="forms")
@SequenceGenerator(name="seq", initialValue=25, allocationSize=100)
public class FormModel implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE,generator = "seq")
    private Long formid;
    private String firstName;
    private String lastName;
    @Column(nullable=false)
    private String Email;
    private long mobileNumber;
    private int overalExperience;
    private int relaventExperience;
    private Date dateOfBirth;
    private String adarNumber;
    @Column(name="name_of_college")
    private String nameOfCollege;
    
    private String certificates;
    
    @OneToMany(mappedBy="formmodel",cascade=CascadeType.ALL,orphanRemoval=true)
    private List<SkillsModel> skills;
}

SkillsModel(技能实体)

@Entity
@Table(name="skills")
public class SkillsModel implements Serializable{

    @Id
     @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name="skill_id")
    private Integer skillid;
    
    @Column(name="skill_name")
    private String skillname;
    
    public SkillsModel() {}
    public SkillsModel(Integer skillid, String skillname) {
        super();
        this.skillid = skillid;
        this.skillname = skillname;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinTable(name="formskills",joinColumns = {@JoinColumn(name="skillid")},inverseJoinColumns = {@JoinColumn(name="formid")})
    private FormModel formmodel;
    
    
    public SkillsModel(Integer skillid, String skillname, FormModel formmodel) {
        super();
        this.skillid = skillid;
        this.skillname = skillname;
        this.formmodel = formmodel;
    }
}

Controller(控制器)

@CrossOrigin(origins = "http://localhost:4200")
@RestController
public class FormController {
    
    @Autowired
    private FormService service;
    
    
    @GetMapping("/getskills")
    public List<SkillsModel> getskills() {
        return service.getskills();
    }
    
    @PostMapping(value="/saveuser")
    public ResponseEntity<Object> createUser(@RequestBody FormModel model) {    
              System.out.println(model.getSkills().get(0));
             FormModel modelform=service.createuserform(model);
           
        URI location=ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(modelform.getFormid()).toUri();
        return ResponseEntity.created(location).build() ;
    }
    
    @GetMapping("/getforms")
    public List<FormModel> getformdata() {
         return service.getformdata();
    }
}

Service(服务层)

@Service
public class FormService {
    
    @Autowired
    private FormRepository formrepo;
    @Autowired
    private Skillsrepository skillsrepo;
    
    public FormModel createuserform(FormModel userform) {
           FormModel modelform=formrepo.save(userform);
        return  modelform;
    }
    
    public List<SkillsModel> getskills() {
        List<SkillsModel> getskills=new ArrayList<>();
        
        getskills=skillsrepo.findAll();
        for(SkillsModel model :getskills) {
            System.out.println(model.getSkillid() + model.getSkillname());
        }
        return getskills;
    }

    public List<FormModel> getformdata() {
         List<FormModel> formlist= formrepo.findAll();
         System.out.println(formlist);
        return formlist;
    }
}
问题分析与解决方案

核心问题

  1. 关联映射配置错误:SkillsModel中的@JoinTable字段映射与数据库实际字段不匹配,且当前用一对多+多对一的方式实现多对多关系,不符合业务逻辑(一个技能可被多个表单关联)
  2. 关联关系未维护:保存表单时,未为选中的技能设置对应的表单引用,JPA无法识别关联关系
  3. 前端数据处理缺失:若前端仅传入技能ID,后端直接接收为SkillsModel实例会被JPA判定为新技能,而非关联已有技能

修复步骤

1. 修正实体关联映射(推荐多对多配置)

表单与技能是多对多关系,直接用@ManyToMany更贴合业务:

  • 修改FormModel的技能关联:
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(
    name = "formskills",
    joinColumns = {@JoinColumn(name = "formid")},
    inverseJoinColumns = {@JoinColumn(name = "skillid", referencedColumnName = "skill_id")}
)
private List<SkillsModel> skills;
  • 移除SkillsModel中的formmodel字段及对应的@ManyToOne、@JoinTable配置,多对多关系只需在一方维护即可

2. 维护关联关系(保留一对多/多对一时)

在FormService的createuserform方法中,为每个技能绑定表单实例:

public FormModel createuserform(FormModel userform) {
    if(userform.getSkills() != null) {
        for(SkillsModel skill : userform.getSkills()) {
            skill.setFormmodel(userform);
        }
    }
    return formrepo.save(userform);
}

3. 处理前端传入的技能ID

如果前端仅传技能ID列表,先从数据库查询真实技能实例再关联:

public FormModel createuserform(FormModel userform) {
    List<SkillsModel> existingSkills = new ArrayList<>();
    if(userform.getSkills() != null) {
        for(SkillsModel skill : userform.getSkills()) {
            skillsrepo.findById(skill.getSkillid()).ifPresent(existingSkills::add);
        }
        userform.setSkills(existingSkills);
        // 若用一对多需绑定表单,多对多则无需此步骤
        existingSkills.forEach(skill -> skill.setFormmodel(userform));
    }
    return formrepo.save(userform);
}

内容的提问来源于stack exchange,提问作者Sirisha K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:25:43