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

Spring Boot REST Hibernate实现根据州ID查询关联所有城市

实现按州ID查询对应城市的修复方案

现有代码无法运行核心是4个问题:

  • JPA实体关联配置错误:City类直接把外键state_id定义为普通整数属性,没有和State类建立正确的关联映射,JPA无法识别外键关系
  • State类的getId()方法返回值类型和id字段类型不匹配:字段定义为int,方法返回值写的long,会引发JPA代理、序列化异常
  • 实体类缺少必要的setter方法,JPA无法完成属性注入
  • 没有编写对应的数据查询逻辑和接口,无法响应GET请求

方案1:标准JPA关联映射实现(推荐)

1. 修正实体类配置

修正后的State实体

@Entity
@Table(name = "states")
public class State {

  @Id
  // 如果id是数据库自增,保留下面的注解,非自增可删除
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;
  private String state;

  // 一对多关联指向City类,mappedBy对应City类里的State属性名
  @OneToMany(cascade = CascadeType.ALL, mappedBy = "state")
  private List<City> cities = new ArrayList<>();

  public State() {}

  // 修正返回值类型和字段类型一致
  public int getId() {
    return id;
  }

  public String getState() {
    return state;
  }

  public List<City> getCities() {
    return cities;
  }

  // 补全setter方法
  public void setId(int id) {
    this.id = id;
  }

  public void setState(String state) {
    this.state = state;
  }

  public void setCities(List<City> cities) {
    this.cities = cities;
  }
}

修正后的City实体

@Entity
@Table(name = "cities")
public class City {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  private String city;

  // 删除原有的int state_id普通属性,替换为多对一关联
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "state_id", referencedColumnName = "id")
  private State state;

  public City() {}

  public long getId() {
    return id;
  }

  public String getCity() {
    return city;
  }

  public State getState() {
    return state;
  }

  // 补全setter方法
  public void setId(long id) {
    this.id = id;
  }

  public void setCity(String city) {
    this.city = city;
  }

  public void setState(State state) {
    this.state = state;
  }
}

2. 编写数据访问层

新建City的Repository接口,继承JpaRepository,直接派生按stateId查询的方法:

public interface CityRepository extends JpaRepository<City, Long> {
  // 方法名对应关联属性的id字段,JPA会自动生成按state_id查询的SQL
  List<City> findAllByState_Id(int stateId);
}

3. 编写接口层

新建GET接口接收stateId参数,调用查询方法返回结果:

@RestController
public class CityController {

  private final CityRepository cityRepository;

  // 构造器注入Repository
  public CityController(CityRepository cityRepository) {
    this.cityRepository = cityRepository;
  }

  // 接口示例:GET /cities?stateId=1 即可返回id为1的州下所有城市
  @GetMapping("/cities")
  public List<City> getCitiesByState(@RequestParam int stateId) {
    return cityRepository.findAllByState_Id(stateId);
  }
}

方案2:无关联映射简化实现

如果不需要通过State实体级联操作City,不需要维护双向关联,可以直接删掉State类里的cities集合字段,不用配置JPA关联,修改量更小:

  1. 给City类原来的state_id字段加列映射注解,补全setter:
@Entity
@Table(name = "cities")
public class City {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private long id;
  private String city;

  // 加@Column注解明确映射数据库字段
  @Column(name = "state_id")
  private int state_id;

  public City() {}

  public long getId() {
    return id;
  }

  public String getCity() {
    return city;
  }

  public int getState_id() {
    return state_id;
  }

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

  public void setCity(String city) {
    this.city = city;
  }

  public void setState_id(int state_id) {
    this.state_id = state_id;
  }
}
  1. CityRepository的查询方法改成直接匹配字段名:
List<City> findAllByState_id(int stateId);
  1. Controller层代码和方案1完全一致,不需要修改。

内容的提问来源于stack exchange,提问作者Kartik Thakur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:30:53