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

如何编写指定MySQL查询的JPA等价实现并修正Repository代码?

修正你的JPA Repository查询实现

我来帮你搞定这个JPA Repository的问题!先看看你原来代码里踩的几个坑:

  • 实体/表名混淆:JPQL是面向实体类的,得用实体类名Indent而不是数据库表名indent
  • 参数绑定错误:不能直接把参数名硬写到字符串里,得用:参数名或者位置参数来绑定方法传入的变量
  • 返回类型不匹配:你的SQL只查status和is_deleted两个字段,但方法返回List<Indent>,JPA没法把少量字段映射成完整的实体对象,得用投影(比如Tuple或者自定义DTO)来接收结果
  • 语法错误:原查询里的单引号位置完全乱了,'status AND is_deleted = 'condition这种写法根本不符合JPQL语法

下面给你几种正确的实现方案,你可以根据需求选:

方案1:用JPQL + Tuple投影(快速实现,无需额外类)

这种方式不用新建类,直接用JPA提供的Tuple来接收两个字段的结果:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import javax.persistence.Tuple;
import java.util.List;

public interface IndentRepository extends JpaRepository<Indent, Long> {
    @Query("SELECT i.status, i.isDeleted FROM Indent i WHERE i.status = :status AND i.isDeleted = :isDeleted")
    List<Tuple> findByStatusAndIsDeleted(@Param("status") String status, @Param("isDeleted") boolean isDeleted);
}

使用的时候可以这样取结果:

List<Tuple> results = indentRepository.findByStatusAndIsDeleted("in progress", false);
for (Tuple tuple : results) {
    String status = (String) tuple.get("status");
    boolean isDeleted = (boolean) tuple.get("isDeleted");
    // 处理数据
}

方案2:自定义DTO投影(类型更安全)

如果你希望返回的结果类型更清晰,不容易出错,可以先创建一个DTO类:

// 请替换成你的实际包路径
package com.yourproject.dto;

public class IndentStatusDto {
    private String status;
    private boolean isDeleted;

    // 注意:构造方法的参数顺序要和JPQL查询的字段顺序完全一致
    public IndentStatusDto(String status, boolean isDeleted) {
        this.status = status;
        this.isDeleted = isDeleted;
    }

    // 可选:添加getter方法方便获取属性
    public String getStatus() {
        return status;
    }

    public boolean isDeleted() {
        return isDeleted;
    }
}

然后修改Repository:

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.yourproject.dto.IndentStatusDto;
import java.util.List;

public interface IndentRepository extends JpaRepository<Indent, Long> {
    @Query("SELECT new com.yourproject.dto.IndentStatusDto(i.status, i.isDeleted) FROM Indent i WHERE i.status = :status AND i.isDeleted = :isDeleted")
    List<IndentStatusDto> findByStatusAndIsDeleted(@Param("status") String status, @Param("isDeleted") boolean isDeleted);
}

使用时直接操作DTO对象,类型更安全:

List<IndentStatusDto> results = indentRepository.findByStatusAndIsDeleted("in progress", false);
for (IndentStatusDto dto : results) {
    String status = dto.getStatus();
    boolean isDeleted = dto.isDeleted();
    // 处理数据
}

方案3:Spring Data JPA方法命名查询(最简洁)

因为你的查询是简单的“等于”条件匹配,Spring Data JPA可以通过方法名自动生成查询,连@Query都不用写:

import org.springframework.data.jpa.repository.JpaRepository;
import com.yourproject.dto.IndentStatusDto;
import java.util.List;

public interface IndentRepository extends JpaRepository<Indent, Long> {
    // 如果需要返回完整的Indent实体(虽然你原SQL只查两个字段,但如果业务需要全量数据的话)
    List<Indent> findByStatusAndIsDeleted(String status, boolean isDeleted);

    // 如果只需要status和isDeleted,用上面的DTO投影
    List<IndentStatusDto> findByStatusAndIsDeleted(String status, boolean isDeleted);
}

这个方法名findByStatusAndIsDeleted会自动映射到JPQL的WHERE i.status = ?1 AND i.isDeleted = ?2,非常省心!

最后提醒一下:要确保你的Indent实体类里的属性和数据库列对应正确,比如数据库列is_deleted对应的实体属性应该是isDeleted(JPA默认驼峰转下划线),或者用@Column(name = "is_deleted")明确标注字段映射关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:13:27