JPQL 的 Spring Boot JPA“查询验证失败”错误

Posted

技术标签:

【中文标题】JPQL 的 Spring Boot JPA“查询验证失败”错误【英文标题】:Spring Boot JPA "Validation failed for query" error for JPQL 【发布时间】:2018-02-23 05:48:11 【问题描述】:

我正在尝试使用 jpa 的自定义查询(不是 nativeQuery,因为我想将结果映射到自定义对象),但我不知道出了什么问题。

存储库类如下所示:

@Repository
public interface ChallengeCompletionRepository extends JpaRepository<ChallengeCompletion, Integer>
    List<ChallengeCompletion> findByUser(int uid);
    List<ChallengeCompletion> findByChallenge(int cid);
    List<ChallengeCompletion> findByUserAndChallenge(int uid, int cid);

    @Query(value = "SELECT new com.some.rly.long.package.name.ChallengeScore(user_id, count(id)) " +
        "FROM ChallengeCompletion " +
        "WHERE challenge_id = :cid " +
        "GROUP BY user_id " +
        "ORDER BY count(id) DESC")
   List<ChallengeScore> fetchUserScoreForChallenge(@Param("cid") int cid);

我想要列出的结果的模型类如下所示:

@Data
@NoArgsConstructor
public class ChallengeScore 

    public ChallengeScore(UUID userId, int score)
        this.score = score;
        this.userId = userId;
    

    private int score;
    private User user;

    @JsonIgnore
    private UUID userId;


这是 ChallengeCompletion 的模型:

@Entity
@Data
@Table(name = "challenge_completions")
public class ChallengeCompletion extends BaseModel

    @ManyToOne
    @JsonBackReference
    private User user;

    @ManyToOne
    private Challenge challenge;

    @ManyToOne
    private Project project;


基础模型是:

@MappedSuperclass
@Data
public abstract class BaseModel 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @CreationTimestamp
    private Timestamp createdAt;

    @UpdateTimestamp
    private Timestamp updatedAt;

错误很简单:“查询验证失败...”。我也觉得我需要为要构建的类使用完全限定名称有点奇怪,.. 但这可能是因为该类不是真正的 @Entity 并且没有自动加载.

可以在此处找到完整的堆栈跟踪:https://pastebin.com/MjP0Xgz4

对于上下文,这个查询应该做的是:一个用户可以完成多次挑战。每个完成都在 ChallengeCompletion 中记录为一行。我想获取不同用户(id)的列表以及他们完成某个挑战的频率。

干杯

编辑:感谢@DN1 的评论,如果您不想提供 Challenge 对象而只想提供 id,那么在发现您确实可以执行 cc.challenge.id 之类的事情后,我可以让它工作:

@Query(value = "SELECT new com.energiedienst.smartcity.middleware.module.challenge.model.ChallengeScore(cc.user, count(cc.id)) " +
        "FROM ChallengeCompletion cc " +
        "WHERE cc.challenge.id = :cid " +
        "GROUP BY cc.user " +
        "ORDER BY count(cc.id) DESC")
List<ChallengeScore> fetchUserScoreForChallenge(@Param("cid") int cid);

ChallengeScore 类现在看起来像:

@Data
@NoArgsConstructor
public class ChallengeScore 

    public ChallengeScore(User user, long score)
        this.score = score;
        this.user = user;
    

    private long score;
    private User user;


【问题讨论】:

您是否尝试过使用投影 (docs.spring.io/spring-data/jpa/docs/current/reference/html/…) 或编写自定义实现 @pvpkiran,感谢您的回答,不确定您对自定义实施的意思。据我了解,上述情况应该有效。我确实有这个问题,我经常需要一个用于自定义查询的中间类,所以我想了解这个问题而不是解决它。该错误表明查询存在语法错误。 你能把完整的堆栈跟踪。投影专门用于中间类的情况。我的意思是你可以编写一个自定义存储库并将ChallengeCompletion转换为ChallengeScore***.com/questions/43265331/… 当类中没有这样的 FIELD 时,您不能使用带有“user_id”的 JPQL。这不是 SQL。但是你没有发布据称这是为了的JPA实体ChallengeCompletion @DN1 我认为您对“user_id”有误:这是应有的 ChallengeCompletion 字段,而不是 ChallengeScore 的字段……也就是说,如果它实际上是该类的字段。 .. 是的,发布实体,这样我们就得到了全貌 【参考方案1】:

异常的原因是您使用的是 JPQL,而 JPQL 使用类/字段名称而不是表/列名称(SQL 使用的名称)。 user_idchallenge_id 看似是列名,您需要更改这些以使用字段名。详情请见this guide。

【讨论】:

以上是关于JPQL 的 Spring Boot JPA“查询验证失败”错误的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot Jpa JPQL 选择除特定列之外的列

Spring jpa jpql查询

Spring JPA 和 Hibernate 的 JPQL 查询错误

没有 JPQL 查询的 Spring-data-jpa 中的 CURRENT_DATE

如何在 JPQL(Spring JPA 查询)中使用 JOIN 执行 UPDATE 语句?

无法在 FROM 子句中使用子查询编写 JPQL 查询 - Spring Data Jpa - Hibernate