arrays - 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
}
}`
解决方案
推荐阅读
- php - “这个集合实例 laravel 上不存在属性 [left_b]?
- ruby-on-rails - 如何组合 simplecov 覆盖/index.html 文件
- typescript - 无法在带有打字稿的 vue 中使用 Mixins
- apache-kafka - kafka connect 跳过获取分区
- python - |_ 在 django 模板标签中
- spring - 在 Spring 中提供静态内容 - 为什么我们需要 addResourceLocations 方法而我们有 addResourceHandler?
- scapy - 为什么 Scapy ICMP 无法得到答案但“ping”工作正常
- python - OpenCV 像素块检测(检测白色像素块)
- php - 如何在wordpress插件的自定义元框中保存多个复选框值?
- laravel - Creating zip of multiple files and download in laravel