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

JPA与PostgreSQL:关联实体外键查询报错的解决方法

解决JPA REST API查询关联实体时的"column rating0_.id does not exist"错误

看起来你遇到的问题核心是实体映射配置不正确,或者JPA查询语句的写法不符合面向实体的规则,导致JPA生成的SQL试图查找不存在的列。咱们一步步来解决:

第一步:先确保实体类的关联映射正确

首先检查你的Rater和Rating实体是否正确配置了一对多关系,这是基础:

Rater实体类(主键+一对多关联)

@Entity
public class Rater {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // 必须有主键映射,数据库表也要对应有id列

    // 其他业务字段,比如name之类的

    // 一对多关联:mappedBy指向Rating实体中关联Rater的属性名
    @OneToMany(mappedBy = "rater", fetch = FetchType.LAZY)
    private List<Rating> ratings;

    // Getters & Setters
}

Rating实体类(主键+多对一关联)

@Entity
public class Rating {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // 这里必须定义主键!你的错误大概率和这个有关——JPA默认需要实体有主键,否则会自动查找id列但找不到

    private Integer rating; // 你的业务字段,比如评分值

    // 多对一关联:@JoinColumn的name要和数据库里的外键列名完全一致(比如你的数据库列是rater_id,这里就写rater_id)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "rater_id")
    private Rater rater;

    // Getters & Setters
}

⚠️ 重点:如果你的Rating实体没有定义@Id的id字段,JPA会默认尝试映射数据库表的id列,而如果你的表没有这个列,就会抛出"column rating0_.id does not exist"的错误!

第二步:选择正确的JPA查询方式

解决完实体映射,接下来用几种简单的方式实现"查询ID为3的Rater的所有Rating":

方式1:Spring Data JPA方法命名查询(最简单)

创建RatingRepository接口,利用Spring Data的方法命名规则自动生成查询:

public interface RatingRepository extends JpaRepository<Rating, Long> {
    // 直接根据rater的id查询所有Rating,Spring Data会自动生成正确的JPQL
    List<Rating> findByRaterId(Long raterId);
}

然后在REST控制器里调用:

@RestController
@RequestMapping("/api")
public class RatingController {
    private final RatingRepository ratingRepository;

    // 构造注入(推荐,替代@Autowired)
    public RatingController(RatingRepository ratingRepository) {
        this.ratingRepository = ratingRepository;
    }

    @GetMapping("/raters/{raterId}/ratings")
    public ResponseEntity<List<Rating>> getRatingsByRaterId(@PathVariable Long raterId) {
        List<Rating> ratings = ratingRepository.findByRaterId(raterId);
        return ResponseEntity.ok(ratings);
    }
}

调用这个接口GET /api/raters/3/ratings就能得到ID为3的Rater的所有评分。

方式2:自定义JPQL查询(更灵活)

如果需要更复杂的查询逻辑,可以用@Query注解写JPQL(面向实体,不是原生SQL):

public interface RatingRepository extends JpaRepository<Rating, Long> {
    @Query("SELECT r FROM Rating r WHERE r.rater.id = :raterId")
    List<Rating> findRatingsByRaterId(@Param("raterId") Long raterId);
}

这里注意JPQL是用实体属性名(r.rater.id),而不是数据库列名(rater_id),JPA会自动帮你转换成对应的SQL。

方式3:通过Rater实体关联获取评分

如果你需要先查询Rater再获取它的评分,可以用Fetch Join避免懒加载异常:
首先创建RaterRepository:

public interface RaterRepository extends JpaRepository<Rater, Long> {
    // Fetch Join一次性加载Rater和它的Ratings,避免懒加载时的NoSessionException
    @Query("SELECT r FROM Rater r JOIN FETCH r.ratings WHERE r.id = :raterId")
    Optional<Rater> findByIdWithRatings(@Param("raterId") Long raterId);
}

然后在控制器里:

@GetMapping("/raters/{raterId}/ratings")
public ResponseEntity<List<Rating>> getRaterRatings(@PathVariable Long raterId) {
    return raterRepository.findByIdWithRatings(raterId)
            .map(rater -> ResponseEntity.ok(rater.getRatings()))
            .orElse(ResponseEntity.notFound().build());
}

为什么你的原查询会出错?

你写的原生SQLSELECT rating FROM Rating rating, Rater rater WHERE rating.rater_id = rater.id AND rater.id = 3;如果直接在JPA里使用(比如不加nativeQuery=true),JPA会把它当成JPQL解析:

  • JPQL里SELECT rating会尝试查询Rating实体的所有字段(包括主键id),但如果你的实体映射有问题,或者数据库表没有id列,就会报错。
  • 正确使用原生SQL的话需要加nativeQuery=true,但不推荐——JPA的优势就是面向实体,尽量用JPQL或方法命名查询。

内容的提问来源于stack exchange,提问作者Kevin Shi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:11:26