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关联,修改量更小:
- 给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; } }
- CityRepository的查询方法改成直接匹配字段名:
List<City> findAllByState_id(int stateId);
- Controller层代码和方案1完全一致,不需要修改。
内容的提问来源于stack exchange,提问作者Kartik Thakur
相关产品推荐
相关产品推荐

