SpringBoot+H2数据库Post请求存入数据为Null问题排查
问题
开发SpringBoot项目时使用H2数据库存储数据,通过Postman发送Post请求提交用户信息(username和email),数据库中这两个字段始终存入Null值。User实体类已包含带参构造器和默认构造器,但传入JSON请求体时仍触发默认构造器,导致属性未赋值。
相关代码如下:
实体类代码
@Entity @Table(name = "users") // Specify the table name public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String email; public User(String username, String email) { this.username = username; this.email = email; } public User() { }
控制器代码
@RestController @RequestMapping("/api/users") public class UserController { .... @PostMapping public User createUser(@RequestBody User user) { System.out.println("Received Request Body: " + user.getUsername()); return userService.createUser(user); }
服务层代码
public User createUser(User user) { return userRepository.save(user); }
Repository代码
public interface UserRepository extends JpaRepository<User, Long> { }
发送的请求体:
{ "username": "john_doe", "email": "john@example.com" }
解决方案
- 核心原因:Spring默认用Jackson做JSON反序列化,当实体类存在带参构造器时,Jackson会优先尝试使用它,但如果不给构造器参数加
@JsonProperty注解,Jackson无法将JSON字段和构造器参数对应,最终会退而使用默认构造器,导致属性没被赋值。 - 解决方法1:添加Getter/Setter方法
给User实体类的username和email字段添加标准Getter、Setter方法。Jackson在无法通过构造器赋值时,会通过Setter方法设置属性值,就能正确映射JSON请求体里的字段。
修改后的实体类示例:@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; private String email; public User(String username, String email) { this.username = username; this.email = email; } public User() { } // 添加Getter和Setter public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } - 解决方法2:给构造器参数添加@JsonProperty注解
在带参构造器的参数上添加@JsonProperty注解,指定对应的JSON字段名,让Jackson能正确匹配参数和JSON字段,直接通过带参构造器创建实例并赋值。
修改后的构造器示例:public User(@JsonProperty("username") String username, @JsonProperty("email") String email) { this.username = username; this.email = email; } - 验证方式:修改后重启项目,发送Post请求,查看控制台打印的
user.getUsername()值,如果能正确输出john_doe,说明反序列化成功,此时存入数据库的字段也会有正确值。
内容的提问来源于stack exchange,提问作者perpetter
相关产品推荐
相关产品推荐

