全栈前端出现奇怪错误 Spring Boot academic project

Strange error in front-end of full-stack Spring Boot academic project

我们被要求为一个学术项目开发一个使用 Java、Maven 和 Spring-Boot 的全栈网络系统,试图遵循 CLEAN 架构和 SOLID原则。老师告诉我,最重要的目标是让后端和前端沟通。我开发的系统很瘦,由几个后端 Java 类 和 MySQL db 和一个简化的前端组成,有 2 HTML 个文件和简洁的 CSS和Java脚本代码。
前端页面包含两个JS异步函数;第一个通过其 id 属性检索食谱名称,另一个尝试检索存储在其各自 MySQL db table 中的完整食谱列表,通过以下 JPA @Query 注释:

@Query (value = "SELECT matricula, registro, nome FROM RECEITA", nativeQuery = true)

预期返回值为:

但实际显示的结果是:

我会认为我在编程方面的专业水平是初学者;不知道哪里错了,涉及的方法和文件太多了。我会粘贴代码,这样也许有人会指出可能的错误。
项目文件夹结构:


App.java:

package com.pucrs.grupo2.Recipes;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@ComponentScan(basePackages = "com.pucrs.grupo2")
@EnableJpaRepositories(basePackages = {"com.pucrs.grupo2"}) // onde procurar as interfaces dos repositórios do JPA
@EntityScan(basePackages = {"com.pucrs.grupo2"}) // onde procurar as entidades
public class App {
    public static void main(String[] args) {
        
        SpringApplication.run(App.class, args);
        
    }
    
}

ClienteFachadaRemota.java:

package com.pucrs.grupo2.Recipes.interfaces;

import java.util.List;
import com.pucrs.grupo2.Recipes.services.ServicoReceitas;
import com.pucrs.grupo2.Recipes.models.Receita;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/consulta_receita")

public class ClienteFachadaRemota {
    private ServicoReceitas sConsultaRec;

    @Autowired    
    public ClienteFachadaRemota (ServicoReceitas sConsultaRec) {
        this.sConsultaRec = sConsultaRec;
    }

    @CrossOrigin(origins = "*")
    @GetMapping("/dadosreceita")
        public Receita getDadosReceita(@RequestParam Long matricula) {
        Receita receita = sConsultaRec.getNomeReceita(matricula);
        return receita;
    }    
    
    @CrossOrigin(origins = "*")
    @GetMapping("/listareceitas")
    public List<Receita> getTabelaReceitas() {
        List<Receita> receitas = sConsultaRec.findTables();
        return receitas;
    }
    
}

Receita.java:

package com.pucrs.grupo2.Recipes.models;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "receita")
public class Receita {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long matricula;
    private int registro;
    private String nome;    

    public Receita() {

    }

    public Receita(int registro, String nome) {
        this.registro = registro;
        this.nome = nome;
    }
    
    
    public Long getMatricula() {
        return matricula;
    }

    
    public int getRegistro() {
        return registro;
    }

    public void setRegistro(int registro) {
        this.registro = registro;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    @Override
    public String toString() {
        return "Receita [matricula=" + getMatricula() + ", registro=" + getRegistro() + ", nome=" + getNome() + "]";
    }

}

RepositorioReceitas.java:

package com.pucrs.grupo2.Recipes.repositories;

import java.util.List;
import com.pucrs.grupo2.Recipes.models.Receita;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.jpa.repository.Query;

public interface RepositorioReceitas extends CrudRepository<Receita, Long> {
    List<Receita> findByMatricula(long matricula);
    List<Receita> findAll();

    @Query (value = "SELECT matricula, registro, nome FROM RECEITA", nativeQuery = true)
    List<Receita> findTables();

}

ServicoReceitas.java:

package com.pucrs.grupo2.Recipes.services;

import com.pucrs.grupo2.Recipes.models.Receita;
import com.pucrs.grupo2.Recipes.repositories.RepositorioReceitas;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class ServicoReceitas {
    private RepositorioReceitas repReceitas;
    private Receita cacheReceita;

    @Autowired
    public ServicoReceitas(RepositorioReceitas repReceitas) {
        this.repReceitas = repReceitas;
        cacheReceita = null;
    }

    public Receita getNomeReceita(long matricula) {
        List<Receita> receitas = repReceitas.findByMatricula(matricula);
        if (receitas.size() == 0){
            throw new IllegalArgumentException("Receita nao encontrada");
        } else {
            cacheReceita = receitas.get(0) ;
            return cacheReceita;
        }
    }

    public List<Receita> listaDeReceitas() {
        List<Receita> receitas = repReceitas.findAll();
        return receitas;
    }

    public List<Receita> findTables() {
        List<Receita> receitas = repReceitas.findTables();
        return receitas;
    }

}

index.html:

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title> Retrieval by id, List Retrieval Recipes System </title>
        <link rel="stylesheet" href="style.css">
    </head>

<body>  
    <h1>Retrieval by id, Recipe List Retrieval System</h1>
      <ul>
        <li>
          <label for="matricula">id:</label>
          <input type="text" id="matricula" name="matricula">
        </li>
        <li>
          <label id="nome">Nome:</label>
          <span id="nomeReceita"> - </span>
        </li>
        <li>
          <button id="btDados">Consultar Nome</button>
          <span id="erro"></span>
        <br>
          <button id="btLista">Mostrar Lista</button>
          <span id="listareceitas"> - </span>
        </li>
      </ul>
    
    <script type="text/javascript" src="./script.js"></script>
  
</body>
</html>

style.css:

.recipes-icon {
    content:url(file:///D:/Documentos/Docs/PUCRS/FdDdSW/TF/TF-FDS/Recipes/src/main/resources/static/r_spatula.jpg);
    width: 800px;
    height: 600px;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}

 div {
    position: fixed;
    color: brown;
    font-family: sans-serif;
    font-size: 300%;
    left: 50%;
    bottom: 100px;
    transform:translate(-50%, -50%);
    margin: 0 auto;
    cursor: pointer;
}

 h1 {
    color: brown;
    width: 100%;
    text-align: center;
  }
  
.ul {
    list-style: none;
    padding: 0;
    margin: 0;
  }
  
.label {
    display: inline-block;
    width: 90px;
    text-align: right;
  }
  
.input {
    font: 1em sans-serif;
    width: 300px;
    box-sizing: border-box;
    border: 1px solid #999;
  }
  
.input:focus {
    border-color: #000;
  }
  
.button {
    margin:auto;
    text-align: center;
  }
  
#erro {
  color:red;
  }

script.js:

//Consulta nome da receita pelo id
async function consultaNomeReceita(matricula) {
    //console.log(matricula);

    let url = "http://localhost:8080/consulta_receita/dadosreceita";
    url = url + "?matricula="+matricula;

    try {
        let resposta = await fetch(url);
        //console.log(resposta);
        if (resposta.ok){
            let dados = await resposta.json();
            //console.log(dados);
            return dados;
        }else{
            //console.log(resposta.status+", text="+resposta.statusText);
            return null;
        }
    }catch(erro){
        console.log(erro);
    }

}

//Mostra Lista Receitas
async function listaReceitas() {
    //console.log(matricula);

    let url = "http://localhost:8080/consulta_receita/listareceitas";
    //url = url + "?matricula="+matricula;

    try {
        let resposta = await fetch(url);
        //console.log(resposta);
        if (resposta.ok) {
            let dados = await resposta.json();
            //console.log(dados);
            return dados;
        } else {
            //console.log(resposta.status+", text="+resposta.statusText);
            return null;
        }
    } catch(erro) {
        console.log(erro);
    }
}

// --- início do programa
document.getElementById("btDados").onclick = async function () {
    let matricula = document.getElementById("matricula").value;
    let resposta = await consultaNomeReceita(matricula);
    if (resposta != null){
        let nome = document.getElementById("nomeReceita");
        nome.innerHTML = resposta.nome;
        erro = document.getElementById("erro");
        erro.innerHTML = "";
        //let json = document.getElementById("jsonValor");
        //json.innerHTML = JSON.stringify(resposta);
    } else {
        let nome = document.getElementById("nomeReceita");
        nome.innerHTML = " - ";
        erro = document.getElementById("erro");
        erro.innerHTML = "Erro na consulta dos dados";
    }

}

document.getElementById("btLista").onclick = async function () {
        let resposta = await listaReceitas();
        if (resposta != null){
            let tables = document.getElementById("listareceitas");
            tables.innerHTML = resposta;
            erro = document.getElementById("erro");
            erro.innerHTML = "";
            //let json = document.getElementById("jsonValor");
            //json.innerHTML = JSON.stringify(resposta);
        } else {
            let tables = document.getElementById("listareceitas");
            tables.innerHTML = " - ";
            erro = document.getElementById("erro");
            erro.innerHTML = "Erro na consulta dos dados";
        }
    
    }

有什么想法吗?
项目的 GitHub 回购 URL:Recipes system

在您的 script.js 文件的最后一段代码中,您试图显示整个 JSON 检索到的对象,您应该遍历整个结果 respota 并将其显示到前端: 应该是这样的:

const response = await fetch('http://localhost:3000/users/'); const data = await response.json();

data.forEach(obj => {
    Object.entries(obj).forEach(([key, value]) => {
        console.log(`${key} ${value}`);
    });
    console.log('-------------------');
});

您可能会发现此 url 也很有用:http://zetcode.com/javascript/jsonforeach/

如@Bleard Rexhaj 所述,您的数据包含一个数组,您可以将代码更改为以下内容。此外,我会考虑为 UI 使用 Javascript 框架,它将大大提高代码的质量。我会考虑的一些流行的是 React.js 或 Vue.js.

document.getElementById("btLista").onclick = async function () {
    let resposta = await listaReceitas();
    if (resposta != null){
        let tables = document.getElementById("listareceitas");
        let innerHTML = '';
        resposta.forEach(obj => {
            innerHTML += ' - ' + obj.nome;
        });
        tables.innerHTML = innerHTML;
        erro = document.getElementById("erro");
        erro.innerHTML = "";
    } else {
        let tables = document.getElementById("listareceitas");
        tables.innerHTML = " - ";
        erro = document.getElementById("erro");
        erro.innerHTML = "Erro na consulta dos dados";
    }

}