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

Spring Boot多ID嵌入式主键接收为Null的问题排查与解决

解决Spring Boot中复合主键(EmbeddedId)JSON绑定为Null的问题

看起来你遇到了Spring Boot REST接口接收复合主键时无法正确绑定的问题,导致两个ID都为Null。这通常是因为Jackson序列化/反序列化规则和JPA嵌入式主键的要求没匹配上,我来帮你一步步解决:

问题根源分析

你的OneTwoKey作为嵌入式主键,需要满足几个关键条件才能被Jackson和JPA正确处理:

  1. 必须有无参构造函数:Jackson需要无参构造来实例化对象,JPA也要求实体类(包括嵌入式主键类)提供无参构造。
  2. 字段需要正确的JSON映射:你的JSON里用的是oneID和twoID,但OneTwoKey里的字段是_oneID,如果没有显式指定JsonProperty,Jackson可能无法正确匹配。
  3. 嵌入式主键类需要实现equals和hashCode:JPA要求嵌入式主键类重写这两个方法,确保主键的唯一性判断正确。
  4. OneTwo类中@EmbeddedId字段的getter/setter映射可能存在问题。

具体修改方案

1. 修正OneTwoKey类

给它添加无参构造,显式指定JsonProperty,并重写equals和hashCode:

import java.io.Serializable;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.persistence.Column;

public class OneTwoKey implements Serializable {
    @JsonProperty("oneID")
    @Column(name = "OneID")
    private int _oneID;
    
    @JsonProperty("twoID")
    @Column(name = "TwoID")
    private int _twoID;

    // 必须添加无参构造函数,Jackson和JPA都需要
    public OneTwoKey() {}

    public OneTwoKey(int oneID, int twoID) {
        this._oneID = oneID;
        this._twoID = twoID;
    }

    // 添加getter和setter,让Jackson能正确赋值
    public int getOneID() {
        return _oneID;
    }

    public void setOneID(int oneID) {
        this._oneID = oneID;
    }

    public int getTwoID() {
        return _twoID;
    }

    public void setTwoID(int twoID) {
        this._twoID = twoID;
    }

    // 重写equals和hashCode,JPA判断主键唯一性的核心依据
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        OneTwoKey oneTwoKey = (OneTwoKey) o;
        return _oneID == oneTwoKey._oneID && _twoID == oneTwoKey._twoID;
    }

    @Override
    public int hashCode() {
        return Objects.hash(_oneID, _twoID);
    }
}

2. 修正OneTwo实体类

确保@EmbeddedId字段的JSON映射正确,同时添加deleted字段的映射(因为你的请求JSON包含这个字段):

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.persistence.Column;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import org.hibernate.annotations.Where;

@Entity(name = "OneTwo")
@Where(clause = "deleted='false'")
public class OneTwo{
    @EmbeddedId
    @JsonProperty("oneTwo") // 直接给嵌入式主键字段指定JSON键名,和请求中的key对应
    private OneTwoKey _id;

    @Column(name = "deleted")
    private boolean deleted;

    // 添加无参构造
    public OneTwo() {}

    public OneTwo(OneTwoKey id) {
        this._id = id;
    }

    // 添加getter和setter
    public OneTwoKey getId() {
        return _id;
    }

    public void setId(OneTwoKey id) {
        this._id = id;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }
}

3. 优化控制器代码(可选但推荐)

把Service改成构造注入,让代码更符合Spring的最佳实践:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OneTwoController {
    private final OneTwoService _service;

    // 构造注入(替代字段注入,更安全、易测试)
    public OneTwoController(OneTwoService service) {
        this._service = service;
    }

    @PostMapping("/api/one-two")
    @CrossOrigin
    public ResponseEntity<ServiceResponse> save(@RequestBody OneTwo model) {
        return ResponseEntity.ok(_service.save(model)); // 简化写法
    }
}

为什么这样修改?

  • 无参构造:Jackson在反序列化JSON时,会先创建对象实例,再通过setter赋值,所以必须有无参构造才能完成实例化。
  • @JsonProperty:显式指定JSON字段和Java字段的映射关系,避免因为命名风格(下划线/驼峰)差异导致的匹配失败。
  • equals和hashCode:JPA在处理嵌入式主键时,依赖这两个方法判断主键是否相同,确保持久化操作的正确性。
  • 添加deleted字段:你的请求JSON包含这个字段,实体类必须有对应的字段才能接收,否则会被Jackson忽略。

这样修改后,你的JSON请求就能正确映射到OneTwo对象,复合主键的oneID和twoID也不会再是Null了。

内容的提问来源于stack exchange,提问作者Pablo De Luca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:43:44