首页 > 解决方案 > Spring Boot - JPARepository - 出现在 _links 中的实体数组,而不是 json 中的数组

问题描述

当我创建我的实体的存储库时,它会将 OneToMany 关系创建为 _links 而不是 Array 属性。但它只发生在一个实体,在餐厅。当我对另一个实体执行相同的过程时,它会按需要工作,它会创建数组。

这是代码:

实体餐厅

`package com.mirestaurante.mirestaurante.entity;

import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import javax.persistence.*;
import java.util.Date;
import java.util.Set;

@Entity
@Table(name = "restaurante")
@Getter
@Setter
public class Restaurante {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "restaurante")
    private Set<ImgRestaurante> imgsRestaurante;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "restaurante")
    private Set<Horario> horarios;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "restaurante")
    private Set<ComentarioRest> comentariosRest;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "restaurante")
    private Set<Pedido> pedidos;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "restaurante")
    private Set<PlatoRestaurante> platosRestaurante;

    @OneToOne
    @PrimaryKeyJoinColumn
    private RestauranteFav restauranteFav;

    @Column(name="nombre")
    private String nombre;

    @Column(name="descripcion")
    private String descripcion;

    @Column(name="img_logo")
    private String imgLogo;

    @Column(name="rango_max_reparto")
    private int rangoMaxReparto;

    @Column(name="destacado")
    private boolean destacado;

    @Column(name="localizacion")
    private String localizacion;

    @Column(name="activo")
    private boolean activo;

    @Column(name = "date_created")
    @CreationTimestamp // Hibernate manejará los timestamps por nosotros
    private Date dateCreated;

    @Column(name = "date_updated")
    @UpdateTimestamp // Hibernate manejará los timestamps por nosotros
    private Date dateUpdated;

    @ManyToOne
    @JoinColumn(name = "categoria_id", nullable = false)
    private Categoria categoria;

}
`

从 restaurante 到 horario 具有 OneToMany 关系的实体 Horario:

`package com.mirestaurante.mirestaurante.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.sql.Time;

@Entity
@Table(name = "horario")
@Getter
@Setter
public class Horario {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "apertura")
    private Time apertura;

    @Column(name = "cierre")
    private Time cierre;

    @Column(name = "dia")
    private int dia;

    @ManyToOne
    @JoinColumn(name = "restaurante_id", nullable = false)
    private Restaurante restaurante;

}
`

和 JpaRepository:

`package com.mirestaurante.mirestaurante.dao;

import com.mirestaurante.mirestaurante.entity.Restaurante;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestParam;

@RepositoryRestResource
@CrossOrigin("http://localhost:4200")
public interface RestauranteRepository extends JpaRepository<Restaurante, Long> {
}
`

现在可以根据需要使用 PlatoRestaurante:`package com.mirestaurante.mirestaurante.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Set;

@Entity
@Table(name = "plato_restaurante")
@Getter
@Setter
public class PlatoRestaurante {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "platoRestaurante")
    private Set<Alergeno> alergenos;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "platoRestaurante")
    private Set<ImgPlato> imgsPlato;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "platoRestaurante")
    private Set<Extra> extras;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "platoRestaurante")
    private Set<ComentarioPlato> comentariosPlato;

    @OneToOne
    @PrimaryKeyJoinColumn
    private PlatoFav platoFav;

    @Column(name = "nombre")
    private String nombre;

    @Column(name = "descripcion")
    private String descripcion;

    @Column(name = "precio_base")
    private BigDecimal precioBase;

    @ManyToOne
    @JoinColumn(name = "restaurante_id", nullable = false)
    private Restaurante restaurante;

}
`

实体 Alergeno,与 PlatoRestaurant 具有 OneToMany 关系:

`package com.mirestaurante.mirestaurante.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Table(name = "alergeno")
@Getter
@Setter
public class Alergeno {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "alergeno")
    private String alergeno;

    @ManyToOne
    @JoinColumn(name = "plato_id", nullable = false)
    private PlatoRestaurante platoRestaurante;

}
`

PlatoRestaurant 的 JpaRepository:

`package com.mirestaurante.mirestaurante.dao;

import com.mirestaurante.mirestaurante.entity.PlatoRestaurante;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import org.springframework.web.bind.annotation.CrossOrigin;

@RepositoryRestResource(collectionResourceRel = "platosRestaurante", path = "platos-restaurante")
@CrossOrigin("http://localhost:4200")
public interface PlatoRestauranteRepository extends JpaRepository<PlatoRestaurante, Long> {
}
`

这两个结果,首先是 Restaurante JSON:

`{
"_embedded": {
"restaurantes": [
{
"id": 1,
"pedidos": [],
"restauranteFav": null,
"nombre": "Taco Bell",
"descripcion": "Comida mejicana y sabrosa",
"imgLogo": "assets/images/TacoBell.png",
"rangoMaxReparto": 1234,
"destacado": true,
"localizacion": "Calle Manuel Candela",
"activo": true,
"dateCreated": "2021-08-13T14:40:42.000+00:00",
"dateUpdated": null,
"_links": {
"self": {
"href": "http://localhost:8080/api/restaurantes/1"
},
"restaurante": {
"href": "http://localhost:8080/api/restaurantes/1"
},
"comentariosRest": {
"href": "http://localhost:8080/api/restaurantes/1/comentariosRest"
},
"horarios": {
"href": "http://localhost:8080/api/restaurantes/1/horarios"
},
"platosRestaurante": {
"href": "http://localhost:8080/api/restaurantes/1/platosRestaurante"
},
"imgsRestaurante": {
"href": "http://localhost:8080/api/restaurantes/1/imgsRestaurante"
},
"categoria": {
"href": "http://localhost:8080/api/restaurantes/1/categoria"
}
}
},
{
"id": 2,
"pedidos": [],
"restauranteFav": null,
"nombre": "Burger King",
"descripcion": "Comida americana y sabrosa",
"imgLogo": "assets/images/BurgerKing.png",
"rangoMaxReparto": 1234,
"destacado": true,
"localizacion": "Calle Manuel Candela",
"activo": true,
"dateCreated": "2021-08-13T14:58:36.000+00:00",
"dateUpdated": null,
"_links": {
"self": {
"href": "http://localhost:8080/api/restaurantes/2"
},
"restaurante": {
"href": "http://localhost:8080/api/restaurantes/2"
},
"comentariosRest": {
"href": "http://localhost:8080/api/restaurantes/2/comentariosRest"
},
"horarios": {
"href": "http://localhost:8080/api/restaurantes/2/horarios"
},
"platosRestaurante": {
"href": "http://localhost:8080/api/restaurantes/2/platosRestaurante"
},
"imgsRestaurante": {
"href": "http://localhost:8080/api/restaurantes/2/imgsRestaurante"
},
"categoria": {
"href": "http://localhost:8080/api/restaurantes/2/categoria"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/api/restaurantes/"
},
"profile": {
"href": "http://localhost:8080/api/profile/restaurantes"
},
"search": {
"href": "http://localhost:8080/api/restaurantes/search"
}
},
"page": {
"size": 20,
"totalElements": 2,
"totalPages": 1,
"number": 0
}
}`

和柏拉图餐厅 json:

`{
"_embedded": {
"platosRestaurante": [
{
"id": 1,
"alergenos": [
{
"id": 1,
"alergeno": "pepinillo",
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/1"
}
}
}
],
"imgsPlato": [
{
"id": 1,
"imagen": "https://tacobell.es/wp-content/uploads/2017/05/05_BODEGON_WEB_560X410_TACOS_X6_09FEB.jpg",
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/1"
}
}
}
],
"extras": [
{
"id": 1,
"nombre": "bacon",
"coste": 0.5,
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/1"
}
}
}
],
"comentariosPlato": [
{
"id": 1,
"email": "taco@tacobell.com",
"comentario": "Buenísimo",
"puntuacion": 10,
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/1"
}
}
}
],
"platoFav": null,
"nombre": "taco Estrella",
"descripcion": "El taco más maravilloso",
"precioBase": 2.99,
"_links": {
"self": {
"href": "http://localhost:8080/api/platos-restaurante/1"
},
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/1"
},
"restaurante": {
"href": "http://localhost:8080/api/platos-restaurante/1/restaurante"
}
}
},
{
"id": 2,
"alergenos": [],
"imgsPlato": [],
"extras": [],
"comentariosPlato": [],
"platoFav": null,
"nombre": "taco Master",
"descripcion": "El taco más deseado",
"precioBase": 1.99,
"_links": {
"self": {
"href": "http://localhost:8080/api/platos-restaurante/2"
},
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/2"
},
"restaurante": {
"href": "http://localhost:8080/api/platos-restaurante/2/restaurante"
}
}
},
{
"id": 3,
"alergenos": [],
"imgsPlato": [],
"extras": [],
"comentariosPlato": [],
"platoFav": null,
"nombre": "Enchilada",
"descripcion": "El placer más carnal",
"precioBase": 3.99,
"_links": {
"self": {
"href": "http://localhost:8080/api/platos-restaurante/3"
},
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/3"
},
"restaurante": {
"href": "http://localhost:8080/api/platos-restaurante/3/restaurante"
}
}
},
{
"id": 4,
"alergenos": [],
"imgsPlato": [
{
"id": 2,
"imagen": "https://s3.eu-central-1.amazonaws.com/www.burgerking.com.mx/wp-content/uploads/sites/3/2021/02/24092120/1200x800_14_BigKing-1-1.png",
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/4"
}
}
}
],
"extras": [
{
"id": 2,
"nombre": "bacon",
"coste": 0.5,
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/4"
}
}
}
],
"comentariosPlato": [
{
"id": 2,
"email": "taco@tacobell.com",
"comentario": "Estupendo",
"puntuacion": 10,
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/4"
}
}
}
],
"platoFav": null,
"nombre": "Big King",
"descripcion": "Nuestra hamburguesa especial",
"precioBase": 2.99,
"_links": {
"self": {
"href": "http://localhost:8080/api/platos-restaurante/4"
},
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/4"
},
"restaurante": {
"href": "http://localhost:8080/api/platos-restaurante/4/restaurante"
}
}
},
{
"id": 5,
"alergenos": [
{
"id": 2,
"alergeno": "pepinillo",
"_links": {
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/5"
}
}
}
],
"imgsPlato": [],
"extras": [],
"comentariosPlato": [],
"platoFav": null,
"nombre": "Whopper",
"descripcion": "La más grande",
"precioBase": 3.99,
"_links": {
"self": {
"href": "http://localhost:8080/api/platos-restaurante/5"
},
"platoRestaurante": {
"href": "http://localhost:8080/api/platos-restaurante/5"
},
"restaurante": {
"href": "http://localhost:8080/api/platos-restaurante/5/restaurante"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/api/platos-restaurante"
},
"profile": {
"href": "http://localhost:8080/api/profile/platos-restaurante"
}
},
"page": {
"size": 20,
"totalElements": 5,
"totalPages": 1,
"number": 0
}
}`

标签: arraysjsonspring-bootspring-data-jpaentity

解决方案


推荐阅读