Spring JSON查询中如何避免返回@IdClass对象
解决JPA复合主键序列化重复字段的问题
嗨,我来帮你搞定这个问题!你遇到的JSON里重复出现siteId和contractId的情况,是因为@IdClass定义的复合主键在序列化时被额外输出了对应的主键对象(也就是那个siteIdObject)。不用DTO的话,有几个简单的方案可以解决:
方案一:改用@EmbeddedId + @JsonUnwrapped(推荐)
这个方法更符合JPA复合主键的规范,同时能让Jackson直接展开主键字段,不会出现嵌套对象:
- 先修改你的
SiteId类,加上@Embeddable注解:
@Embeddable public class SiteId implements Serializable { private Integer siteId; private Integer contractId; // 保留原有的setter、getter、构造方法、hash和equals }
- 然后修改
Site实体类,把原来的两个@Id字段替换成@EmbeddedId,并加上@JsonUnwrapped注解让Jackson展开主键字段:
@Entity @Table(name = "site", schema="public") public class Site { @EmbeddedId @JsonUnwrapped private SiteId siteId; private String name; @JsonIgnore @OneToMany(cascade=CascadeType.ALL, mappedBy = "site") public Set<Device> devices; // 保留原有的setter、getter、构造方法、hash和equals }
这样序列化后,返回的JSON就会直接包含siteId、contractId和name,不会有多余的嵌套对象。
方案二:直接忽略多余的序列化字段
如果你不想修改现有的@IdClass结构,可以在Site类上添加@JsonIgnoreProperties注解,指定忽略那个多余的siteIdObject字段:
@Entity @IdClass(SiteId.class) @Table(name = "site", schema="public") @JsonIgnoreProperties({"siteIdObject"}) // 忽略多余的主键对象字段 public class Site { // 保留原有的字段和方法 }
这个方法更简单直接,不需要改动主键的定义方式,就能让Jackson序列化时跳过那个重复的字段。
方案三:检查是否存在额外的getter方法
有时候如果不小心生成了获取主键对象的getter方法(比如public SiteId getSiteIdObject()),Jackson会自动把它序列化出来。如果是这种情况,只需要在这个方法上加上@JsonIgnore注解就行:
@JsonIgnore public SiteId getSiteIdObject() { return new SiteId(siteId, contractId); }
这几个方案都不需要用DTO,应该能完美解决你的问题~
内容的提问来源于stack exchange,提问作者Daniel BESSAIX
相关产品推荐
相关产品推荐

