Spring Boot使用OneToMany映射时无法向子表插入数据如何解决?
问题修复方案
错误原因
- 你的
@OneToMany关联使用了@JoinTable注解,该注解用于配置多对多关联的中间表,但从报错和表结构来看,你的子表recipe_ingredients、recipe_steps本身就带有recipe_id外键字段,且设为非空无默认值。使用@JoinTable时Hibernate只会将关联关系写入中间表,不会自动填充子表的recipe_id字段,因此插入子表时触发非空约束报错。
修复方案(二选一即可)
方案1:使用单向OneToMany关联(无需修改子实体)
直接移除@JoinTable注解,替换为@JoinColumn指定外键字段即可,父实体Recipe的关联配置修改为:
@OneToMany(fetch = FetchType.LAZY , cascade = CascadeType.ALL) @JoinColumn(name = "recipe_id") // 对应子表中的外键字段名 private List<RecipeIngredient> recipeIngredientList; @OneToMany(fetch = FetchType.LAZY , cascade = CascadeType.ALL) @JoinColumn(name = "recipe_id") // 对应子表中的外键字段名 private List<RecipeSteps> recipeSteps;
该方案下不需要修改子实体和插入代码,Hibernate插入子表时会自动填充recipe_id值。
方案2:使用双向OneToMany关联(性能更优)
- 先在子实体类中添加父实体的关联注解,以
RecipeIngredient为例:
// 新增到RecipeIngredient类中 @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "recipe_id") private Recipe recipe; // 同时补全对应的getter、setter方法 // RecipeSteps类也做相同配置
- 修改父实体Recipe的关联注解,使用
mappedBy指定关联属性,移除@JoinTable:
@OneToMany(mappedBy = "recipe", fetch = FetchType.LAZY , cascade = CascadeType.ALL) private List<RecipeIngredient> recipeIngredientList; @OneToMany(mappedBy = "recipe", fetch = FetchType.LAZY , cascade = CascadeType.ALL) private List<RecipeSteps> recipeSteps;
- 修改插入代码,维护双向关联,给每个子对象设置父实体:
// 给所有RecipeIngredient设置关联的recipe对象 List<RecipeIngredient> list = new ArrayList<>(); RecipeIngredient salt = new RecipeIngredient("salt","2kg"); salt.setRecipe(recipe); list.add(salt); RecipeIngredient sugar = new RecipeIngredient("sugar","5kg"); sugar.setRecipe(recipe); list.add(sugar); // 给所有RecipeSteps设置关联的recipe对象 List<RecipeSteps> steps = new ArrayList<>(); RecipeSteps step1 = new RecipeSteps("Step 1","chopping","chop the mf vegetables"); step1.setRecipe(recipe); steps.add(step1); RecipeSteps step2 = new RecipeSteps("Step 2","boiling","boil them rock hard"); step2.setRecipe(recipe); steps.add(step2);
内容的提问来源于stack exchange,提问作者MAYANK DEVRANI
相关产品推荐
相关产品推荐

