Как использовать @RestController (Spring) с дочерним списком объектов - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь создать службу REST с помощью Spring.Все работает, пока я не попытаюсь добавить Список объектов (CartItem) в мой основной объект (Корзина).

Это мой основной объект

@Entity
@Table(name="cart")
public class Cart implements Serializable{
   ...
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   @Id
   @Column(name="id")
   private Integer id;  

   /*when I add this I get the error. If I remove this, the 
   REST service works*/
   @OneToMany(mappedBy="cart", fetch = FetchType.EAGER)
   private List<CartItem> cartItems; 

   //getter, setter, constructors, other fields ecc.
}

Это объект внутри Списка:

@Entity
@Table(name="cart_item")
public class CartItem implements Serializable{
   ...
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   @Id
   @Column(name="id")
   private Integer id; 

   @OneToOne(targetEntity = Product.class, cascade = CascadeType.ALL)
   @JoinColumn(referencedColumnName="productId", name="product_id" )    
   private Product product;     

   @ManyToOne 
   @JoinColumn(name="cart_id", nullable=false)     
   private Cart cart;

  //getter, setter, constructors, other fields ecc.
}

Это мой контроллер

@RestController
@RequestMapping(value="rest/cart")
public class CartRestController {
  ...
    @RequestMapping(value = "/", method = RequestMethod.GET) 
    public List<Cart> readAll() { 
        return cartService.read(); 
    }
 ...
}

Я получаю эту ошибку:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path 
[/webstore] threw exception [Request processing failed; nested exception
 is org.springframework.http.converter.HttpMessageNotWritableException: 
Could not write JSON: Infinite recursion (StackOverflowError); nested
 exception is com.fasterxml.jackson.databind.JsonMappingException: 
Infinite recursion (StackOverflowError) (through reference chain:...

Я полагаю, что мне пришлось управлять списком внутри объекта Корзина вопределенным образом, возможно, потому что я использую JPA, но я все еще не нашел решения в Интернете.Кто-нибудь может мне помочь?

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Это проблема рекурсии сериализации, потому что CartItem имеет двунаправленное отображение обратно в корзину.Так что получается, что

  • корзина сериализуется в JSON
    • все CartItems внутри нее сериализуются в JSON
      • свойство Cart внутри CartItem сериализуется в JSON
        • CartItems внутри корзины сериализуются в json и т. Д. И т. Д.

Возможно, вы будетеВы хотите исключить поле CartItem.cart из сериализации, пометив его аннотацией @JsonIgnore.


Слишком легко представить слишком много информации внешнему миру, если вы используете объекты JPA напрямуювнутри ваших веб-сервисов.На самом деле у Джексона есть полезная функция, называемая JsonView , которая позволяет вам определять, какие свойства будут доступны, вы даже можете настроить их для каждого вызова веб-службы.

0 голосов
/ 22 ноября 2018

бесконечный список?Вы имели в виду исключение stackOverFlow?

Если ситуация такая же, как я сказал, тогда вы должны проверить что-то вроде типа выборки и метода toString () или equal () сущностей или что-то в этом роде.

Например, существуют сущности с именами A и B, и их отношение одно к многим (A - это одно). Если вы сконфигурируете оба их fetchType как Eager, то когда jpa-запрос A, он также будет запрашивать B.Но B также содержит A, поэтому jpa снова будет запрашивать A. Этот вид циклического цикла вызовет stackOverFlow.

Кстати, как насчет предоставления дополнительной информации о вашей проблеме, такой как имя исключения? Это слишком сложно дляя хочу дать вам конкретное решение, все, что я могу сделать, это рассказать вам о некоторых опытах, с которыми я встречался раньше.


Ну, я создал небольшой проект с SpringBoot 2.1.0 и MySql.

Это мой cartItem

public class CartItem {
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Id
    @Column(name="id")
    private Integer id;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name="cart_id", nullable=false)
    private Cart cart;
}

и моя корзина:

public class Cart {
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    @Id
    @Column(name="id")
    private Integer id;

    @OneToMany(mappedBy="cart", fetch = FetchType.EAGER)
    private List<CartItem> cartItems;
}

Контроллер такой же, как вы написали. После добавления @JsonIgnore в корзину, созданную из CartItem, цикл кругаболее (BeforНапример, у программы возникла проблема с циклическим циклом.)

Каждый раз, когда вы используете jpa с @ oneToMany, @ ManyToOne или @ ManyToMany, вы должны быть осторожны с этой проблемой.создание экземпляра объекта, печать объекта или чего-то в этом роде. И, конечно, есть много способов решить его, например, изменить тип выборки на LAZY, добавить @ JsonIgnore, переопределить toString () и метод equal ().

...