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

Spring Boot执行Inner Join查询报错,需实现Angular前端数据展示

解决Spring Boot HQL关联查询报错及关联数据获取问题

问题概述

执行INNER JOIN查询时抛出错误:

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: persona is not mapped

对应的HQL语句为:

SELECT name,apellidos,fechaturno,medico FROM persona c INNER JOIN turnos c1 ON c.id = c1.idturno

需求是获取用户(Persona)的姓名、姓氏,以及其关联的预约(Turno)日期和医生信息,最终在Angular前端展示。

错误原因分析

  1. HQL语法错误:HQL是面向实体类的查询,需使用实体类名称(首字母大写),而非数据库表名。原HQL中使用了小写的persona、turnos,Hibernate无法匹配到对应的映射实体。
  2. 关联条件错误:Turno与Persona的关联依赖实体中的persona字段(@ManyToOne注解),无需手动写数据库字段的关联条件。
  3. 返回类型不匹配:查询返回的是零散字段组合,但方法声明返回List<Turno>,类型完全不兼容。

修复步骤

1. 创建DTO封装查询结果

因为查询返回的是跨实体的零散字段,需要自定义DTO类来接收数据:

public class PersonaTurnoDTO {
    private String name;
    private String apellidos;
    private String fechaturno;
    private String medico;

    // 构造方法需与查询字段顺序完全一致
    public PersonaTurnoDTO(String name, String apellidos, String fechaturno, String medico) {
        this.name = name;
        this.apellidos = apellidos;
        this.fechaturno = fechaturno;
        this.medico = medico;
    }

    // Getter方法
    public String getName() { return name; }
    public String getApellidos() { return apellidos; }
    public String getFechaturno() { return fechaturno; }
    public String getMedico() { return medico; }
}

2. 修正Repository中的HQL查询

使用实体类名和已有的实体关联关系重构查询,指定返回DTO类型:

@Repository
public interface TurnoRepository extends JpaRepository<Turno, Integer> {
    // 查询所有用户的预约信息
    @Query("SELECT new com.yourpackage.dto.PersonaTurnoDTO(p.name, p.apellidos, t.fechaturno, t.medico) FROM Persona p INNER JOIN p.turnos t")
    List<PersonaTurnoDTO> findAllPersonaTurnos();

    // 根据用户ID查询其专属预约信息
    @Query("SELECT new com.yourpackage.dto.PersonaTurnoDTO(p.name, p.apellidos, t.fechaturno, t.medico) FROM Persona p INNER JOIN p.turnos t WHERE p.id = :personaId")
    List<PersonaTurnoDTO> findPersonaTurnosByPersonaId(@Param("personaId") int personaId);

    // 保留原有方法
    Turno findById(int idturno);
}

注意替换com.yourpackage.dto为你实际的DTO包路径。

3. 新增Service层封装逻辑(可选)

如果需要在Service层处理业务逻辑,新增对应方法:

@Service
public class TurnoService {
    @Autowired
    private TurnoRepository turnoRepository;

    public List<PersonaTurnoDTO> getAllPersonaTurnos() {
        return turnoRepository.findAllPersonaTurnos();
    }

    public List<PersonaTurnoDTO> getPersonaTurnosByPersonaId(int personaId) {
        return turnoRepository.findPersonaTurnosByPersonaId(personaId);
    }
}

4. 编写REST接口供Angular调用

创建Controller提供数据接口:

@RestController
@RequestMapping("/api/turnos")
public class TurnoController {
    @Autowired
    private TurnoService turnoService;

    @GetMapping("/persona-turnos")
    public ResponseEntity<List<PersonaTurnoDTO>> getAllPersonaTurnos() {
        List<PersonaTurnoDTO> data = turnoService.getAllPersonaTurnos();
        return ResponseEntity.ok(data);
    }

    @GetMapping("/persona-turnos/{personaId}")
    public ResponseEntity<List<PersonaTurnoDTO>> getPersonaTurnosByPersonaId(@PathVariable int personaId) {
        List<PersonaTurnoDTO> data = turnoService.getPersonaTurnosByPersonaId(personaId);
        return ResponseEntity.ok(data);
    }
}

Angular前端展示实现

定义数据接口

export interface PersonaTurno {
  name: string;
  apellidos: string;
  fechaturno: string;
  medico: string;
}

组件中获取并展示数据

import { HttpClient } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { PersonaTurno } from './models/persona-turno.model';

@Component({
  selector: 'app-persona-turnos',
  templateUrl: './persona-turnos.component.html'
})
export class PersonaTurnosComponent implements OnInit {
  personaTurnos: PersonaTurno[] = [];

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.http.get<PersonaTurno[]>('/api/turnos/persona-turnos')
      .subscribe(data => {
        this.personaTurnos = data;
      });
  }
}

HTML模板渲染数据

<table>
  <thead>
    <tr>
      <th>姓名</th>
      <th>姓氏</th>
      <th>预约日期</th>
      <th>医生</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let item of personaTurnos">
      <td>{{ item.name }}</td>
      <td>{{ item.apellidos }}</td>
      <td>{{ item.fechaturno }}</td>
      <td>{{ item.medico }}</td>
    </tr>
  </tbody>
</table>

内容的提问来源于stack exchange,提问作者Federico Andres Ratcliffe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:41:03