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

Spring Data JPA多表关联查询及存储过程调用实现咨询

在Spring Boot中实现关联表数据的自定义展示

前提假设

假设你的三张表对应以下实体(根据实际结构调整):

  • 表A → 实体A:字段id(主键)、name
  • 表B → 实体B:字段id(主键)、tname
  • 表C → 实体C:字段id(主键)、idA(外键关联A.id)、idB(外键关联B.id)、subtype(对应展示的Subtype列)

首先需要创建一个DTO/投影接口来接收自定义查询结果,因为要返回非实体的自定义列:

方式1:使用DTO类

public class DisplayDTO {
    private String name;
    private String type;
    private String subtype;

    // 用于JPQL构造查询的构造函数
    public DisplayDTO(String name, String type, String subtype) {
        this.name = name;
        this.type = type;
        this.subtype = subtype;
    }

    // getter和setter方法
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getType() { return type; }
    public void setType(String type) { this.type = type; }
    public String getSubtype() { return subtype; }
    public void setSubtype(String subtype) { this.subtype = subtype; }
}

方式2:使用投影接口(更简洁)

public interface DisplayProjection {
    String getName(); // 对应查询结果的name列
    String getType(); // 对应查询结果的type列
    String getSubtype(); // 对应查询结果的subtype列
}

1. 编写查询语句获取数据

Spring Data JPA支持JPQL和原生SQL两种查询方式,任选其一即可。

1.1 JPQL查询(推荐,与数据库无关)

在C的Repository接口中添加查询方法:

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;

public interface CRepository extends CrudRepository<C, Long> {
    // 使用DTO接收结果
    @Query("SELECT new com.example.yourpackage.DisplayDTO(a.name, b.tname, c.subtype) " +
           "FROM C c " +
           "JOIN A a ON c.idA = a.id " +
           "JOIN B b ON c.idB = b.id")
    List<DisplayDTO> getDisplayData();

    // 或者使用投影接口
    @Query("SELECT a.name AS name, b.tname AS type, c.subtype AS subtype " +
           "FROM C c " +
           "JOIN A a ON c.idA = a.id " +
           "JOIN B b ON c.idB = b.id")
    List<DisplayProjection> getDisplayDataViaProjection();
}

1.2 原生SQL查询(适合复杂SQL或数据库特定语法)

同样在CRepository中添加:

@Query(value = "SELECT a.name AS name, b.tname AS type, c.subtype AS subtype " +
               "FROM c_table c " +
               "JOIN a_table a ON c.id_a = a.id " +
               "JOIN b_table b ON c.id_b = b.id",
       nativeQuery = true)
List<DisplayDTO> getDisplayDataNative();

// 投影接口也适用原生SQL
@Query(value = "SELECT a.name AS name, b.tname AS type, c.subtype AS subtype " +
               "FROM c_table c " +
               "JOIN a_table a ON c.id_a = a.id " +
               "JOIN b_table b ON c.id_b = b.id",
       nativeQuery = true)
List<DisplayProjection> getDisplayDataNativeViaProjection();

2. 通过存储过程实现操作

2.1 第一步:在数据库中创建存储过程

以MySQL为例,执行以下SQL创建存储过程:

DELIMITER //
CREATE PROCEDURE GetDisplayData()
BEGIN
    SELECT a.name AS name, b.tname AS type, c.subtype AS subtype
    FROM c_table c
    JOIN a_table a ON c.id_a = a.id
    JOIN b_table b ON c.id_b = b.id;
END //
DELIMITER ;

(其他数据库如Oracle、PostgreSQL的存储过程语法略有不同,需对应调整)

2.2 第二步:在Spring Boot中调用存储过程

有两种常用方式:

方式1:通过Spring Data JPA Repository调用

首先在C实体类上添加存储过程注解:

import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.Entity;
import javax.persistence.Table;

@NamedStoredProcedureQuery(
    name = "C.getDisplayData", // 自定义名称,需与Repository方法的@Procedure参数一致
    procedureName = "GetDisplayData", // 数据库中存储过程的名称
    resultClasses = DisplayDTO.class // 返回结果的DTO类
)
@Entity
@Table(name = "c_table")
public class C {
    // 实体字段定义,例如:
    // @Id
    // @GeneratedValue(strategy = GenerationType.IDENTITY)
    // private Long id;
    // private Long idA;
    // private Long idB;
    // private String subtype;
}

然后在CRepository中添加调用方法:

import org.springframework.data.jpa.repository.Procedure;

public interface CRepository extends CrudRepository<C, Long> {
    @Procedure(name = "C.getDisplayData")
    List<DisplayDTO> getDisplayDataFromProcedure();
}

方式2:通过EntityManager手动调用

适合需要更灵活控制的场景,在Service层实现:

import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.StoredProcedureQuery;
import java.util.ArrayList;
import java.util.List;

@Service
public class CService {
    @PersistenceContext
    private EntityManager entityManager;

    public List<DisplayDTO> getDisplayDataViaProcedure() {
        // 创建存储过程查询
        StoredProcedureQuery query = entityManager.createStoredProcedureQuery("GetDisplayData");

        // 获取结果并映射到DTO
        List<Object[]> resultList = query.getResultList();
        List<DisplayDTO> dtoList = new ArrayList<>();
        for (Object[] result : resultList) {
            DisplayDTO dto = new DisplayDTO(
                (String) result[0], // name
                (String) result[1], // type
                (String) result[2]  // subtype
            );
            dtoList.add(dto);
        }
        return dtoList;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:27:16