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

Spring JPA实体关联查询出现String转Long转换失败问题求助

解决Spring JPA中通过国家编码查询州的类型转换错误

我之前碰到过类似的问题,咱们先拆解下问题根源:你用@RepositoryRestResource时,Spring Data REST的默认路径匹配规则把findByCountryCode当成了State实体的ID(Long类型)来解析,所以才会抛出字符串转Long的异常。下面是具体的修复步骤和优化建议:

问题重现

你实现了Country和State的关联实体,然后在StateRepository中定义了自定义查询方法,但测试时访问http://localhost:8080/api/states/findByCountryCode?code=BR时触发错误:

Failed to convert from type [java.lang.String] to type [java.lang.Long] for value 'findByCountryCode'; nested exception is java.lang.NumberFormatException: For input string: "findByCountryCode"

你的实体和Repository代码如下:

Country实体

@Entity 
@Table(name="COUNTRY",catalog ="SPRINGANGULAR") 
@Data 
@NoArgsConstructor 
@AllArgsConstructor 
@EqualsAndHashCode(of = {"id","code","countryName"}, exclude = "states") 
public class Country { 
    @Id 
    @SequenceGenerator(name="COUNTRY_SEQ", sequenceName="COUNTRY_SEQ", allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="COUNTRY_SEQ") 
    @Column(name="ID", nullable = false) 
    private long id; 
    @Column(name="CODE") 
    private String code; 
    @Column(name="COUNTRY_NAME") 
    private String countryName; 
    @OneToMany(fetch=FetchType.LAZY,mappedBy="country", cascade= CascadeType.ALL) 
    private Set<State> states = new HashSet<State>(); 
    public Country(String code, String countryName) { 
        super(); 
        this.code = code; 
        this.countryName = countryName; 
    } 
}

State实体

@Entity 
@Table(name="STATE",catalog ="SPRINGANGULAR") 
@Data 
@NoArgsConstructor 
@AllArgsConstructor 
@EqualsAndHashCode(of = {"id", "stateName"}) 
public class State { 
    @Id 
    @SequenceGenerator(name="STATE_SEQ", sequenceName="STATE_SEQ", allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="STATE_SEQ") 
    @Column(name="ID", nullable = false) 
    private long id; 
    @Column(name="STATE_NAME") 
    private String stateName; 
    @ManyToOne(fetch=FetchType.LAZY,cascade= CascadeType.ALL) 
    @JoinColumn(name = "COUNTRY_ID", nullable = false) 
    private Country country; 
    public State(String stateName, Country country) { 
        super(); 
        this.stateName = stateName; 
        this.country = country; 
    } 
}

问题出在StateRepository

@CrossOrigin("http://localhost:4200") 
@RepositoryRestResource(collectionResourceRel = "states", path = "states") 
public interface StateRepository extends JpaRepository<State, Long>{ 
    @Query("SELECT s FROM State s \n" + "LEFT JOIN Country c ON c.id = c.id \n" + "WHERE c.code = :code \n" + "ORDER BY s.id ASC") 
    List<State> findByCountryCode(@RequestParam("code") String code); 
}

具体修复步骤

1. 给自定义查询方法添加@RestResource注解

Spring Data REST不会自动识别自定义查询方法作为端点,你需要用@RestResource明确指定它的路径。同时还要修正JPQL的错误关联语句:

@CrossOrigin("http://localhost:4200") 
@RepositoryRestResource(collectionResourceRel = "states", path = "states") 
public interface StateRepository extends JpaRepository<State, Long>{ 
    // 用@RestResource指定查询端点的路径和关系名
    @RestResource(path = "by-country-code", rel = "by-country-code")
    // 修正JPQL:直接通过实体关联字段查询,不需要手动写ON条件
    @Query("SELECT s FROM State s JOIN s.country c WHERE c.code = :code ORDER BY s.id ASC")
    // 用@Param映射JPQL中的参数,而不是@RequestParam
    List<State> findByCountryCode(@Param("code") String code); 
}

2. 使用正确的请求路径

Spring Data REST的自定义查询默认挂载在/search路径下,所以你需要用这个URL测试:

http://localhost:8080/api/states/search/by-country-code?code=BR

3. 额外的优化建议

  • 修正State实体的级联策略:你给@ManyToOne设置了CascadeType.ALL,这意味着删除State时会级联删除对应的Country,这通常不符合业务逻辑,建议改成CascadeType.PERSIST(仅保存时级联)或者移除该属性(根据实际需求调整)。
  • JPQL查询优化:原来的LEFT JOIN Country c ON c.id = c.id是无效的关联条件,直接使用s.country即可让JPA自动处理表关联,既简洁又不易出错。

内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 13:42:50