SpringBoot ManyToOne关联保存报错:Field 'user_id'无默认值
问题解决方案
核心问题分析
你遇到的Field 'user_id' doesn't have a default value错误,根源有两个:
- 实体类
Item的@JoinColumn设置了insertable=false, updatable=false,这会让JPA完全不处理user_id字段的插入和更新操作,导致数据库收到的记录里user_id为空,而数据库中该字段是NOT NULL约束,因此报错。 - 控制器的
itemAdd方法里,没有把当前登录用户关联到要保存的Item对象上;另外Item类里的用户getter方法不符合JavaBean规范,会导致属性绑定或JPA操作异常。
具体修改步骤
1. 修复Item实体类
- 修正用户属性的getter方法名称(符合JavaBean规范)
- 移除
@JoinColumn中的insertable=false, updatable=false - 调整级联操作(如果登录用户是已存在的,不需要
CascadeType.ALL,避免误删用户)
修改后的Item实体关键代码:
@Entity @Table(name = "msItem") public class Item { // ... 其他属性和方法保持不变 // 调整级联操作,用PERSIST/MERGE更合理,也可根据需求去掉cascade @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn(name = "user_id", referencedColumnName = "id", nullable = false) private User user; // 修正getter方法名称 public User getUser() { return user; } public void setUser(User user) { this.user = user; } // ... 其他方法保持不变 }
2. 控制器中关联当前登录用户
在itemAdd方法里,先获取当前登录的用户,再设置到Item对象上,然后保存。如果用Spring Security,有两种常用方式:
方式一:使用@AuthenticationPrincipal(推荐)
@Controller public class ProductController { @Autowired private ItemRepository itemRepository; @GetMapping("/listItem") public String listing(Model model) { model.addAttribute("item", new Item()); return "addItem"; } @PostMapping("/process_Item") // 替换成你实际的用户实体类 public String itemAdd(Item item, @AuthenticationPrincipal User currentUser) { // 关联当前登录用户 item.setUser(currentUser); itemRepository.save(item); return "home_page"; } }
方式二:使用SecurityContextHolder
@PostMapping("/process_Item") public String itemAdd(Item item) { // 获取当前登录用户 Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); User currentUser = (User) authentication.getPrincipal(); item.setUser(currentUser); itemRepository.save(item); return "home_page"; }
3. 验证数据库表结构
确保msItem表中的user_id字段是外键,关联到用户表的id字段,且设置为NOT NULL(和实体类的约束一致)。
内容的提问来源于stack exchange,提问作者James Coding
相关产品推荐
相关产品推荐

