I have two classes, which has a @ManyToMany relationship generating the third table described in the code below:
Card
package br.com.rpgnext.deck.critical.model;
import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
import java.io.Serializable;
import java.util.*;
@Entity
@Table(name = "cards")
public class Card implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JoinColumn(name = "id")
private Long id;
private String image;
@ManyToMany(cascade = CascadeType.DETACH, fetch = FetchType.LAZY)
@JoinTable(name = "cards_items", joinColumns = @JoinColumn(name = "card_id"), inverseJoinColumns = @JoinColumn(name = "item_id"))
private Set items;
@Temporal(TemporalType.DATE)
@JsonFormat(pattern = "YYYY-MM-dd")
private Date onCreate;
@PrePersist
public void prePersist(){
this.onCreate = new Date();
}
public Card() {
}
public Card(String image) {
this.image = image;
}
public Card(String image, Set items) {
this.image = image;
this.items = items;
}
public Card(String image, Set items, Date onCreate) {
this.image = image;
this.items = items;
this.onCreate = onCreate;
}
public Card(Long id, String image, Set items, Date onCreate) {
this.image = image;
this.items = items;
this.onCreate = onCreate;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Set getItems() {
return items;
}
public void setItems(Set items) {
this.items = items;
}
public Date getOnCreate() {
return onCreate;
}
public void setOnCreate(Date onCreate) {
this.onCreate = onCreate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return Objects.equals(id, card.id) &&
Objects.equals(image, card.image) &&
Objects.equals(items, card.items) &&
Objects.equals(onCreate, card.onCreate);
}
@Override
public int hashCode() {
return Objects.hash(id, image, items, onCreate);
}
}
Item
package br.com.rpgnext.deck.critical.model;
import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
import java.util.Objects;
@Entity
@Table(name = "items")
public class Item implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JoinColumn(name = "id")
private Long id;
private String title;
private String description;
@OneToOne
@JoinColumn(name="type_id", referencedColumnName = "id")
private Type type;
@ManyToMany(fetch = FetchType.EAGER, mappedBy = "items" )
private Set cards;
@Temporal(TemporalType.DATE)
@JsonFormat(pattern = "YYYY-MM-dd")
private Date onCreate;
@PrePersist
void prePersist(){
this.onCreate = new Date();
}
public Item() {
}
public Item(Long id){
this.id = id;
}
public Item(Long id, String title, String description, Type type, Set cards, Date onCreate) {
this.title = title;
this.description = description;
this.type = type;
this.cards = cards;
this.onCreate = onCreate;
}
public Item(String title, String description, Type type, Set cards) {
this.title = title;
this.description = description;
this.type = type;
this.cards = cards;
}
public Item(Set cards) {
this.cards = cards;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public Set getCards() {
return cards;
}
public void setCards(Set cards) {
this.cards = cards;
}
public Date getOnCreate() {
return onCreate;
}
public void setOnCreate(Date onCreate) {
this.onCreate = onCreate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return Objects.equals(id, item.id) &&
Objects.equals(title, item.title) &&
Objects.equals(description, item.description) &&
Objects.equals(type, item.type) &&
Objects.equals(cards, item.cards) &&
Objects.equals(onCreate, item.onCreate);
}
@Override
public int hashCode() {
return Objects.hash(id, title, description, type, cards, onCreate);
}
}
Type
package br.com.rpgnext.deck.critical.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
import javax.persistence.*;
@Entity
@Table(name = "types")
public class Type implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String text;
private String image;
@Temporal(value = TemporalType.DATE)
@JsonFormat(pattern = "YYYY-MM-dd")
private Date onCreate;
@PrePersist
void prePersists(){
this.onCreate = new Date();
}
public Type() {
}
public Type(String text) {
this.text = text;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Type type = (Type) o;
return Objects.equals(id, type.id) &&
Objects.equals(text, type.text) &&
Objects.equals(image, type.image) &&
Objects.equals(onCreate, type.onCreate);
}
@Override
public int hashCode() {
return Objects.hash(id, text, image, onCreate);
}
}
It has been tried several ways to get the Infonite Loop from JSON, since both classes have a List, but without success.
@JsonIgnore does not resolve because it will not show the content I need.
Inserted JSON sample
{
"image": "Carta-Critica-001.jpg",
"items": [
{"id": 1},
{"id": 2},
{"id": 3},
{"id": 4}
]
}
How would you like me to come back
{
"image": "Carta-Critica-01.jpg",
"items": [
{
"id": 1,
"title": "traqueia esmagada",
"type": {
"id": 1,
"text": "contusão",
"image": "contution.png"
},
"description": "Danos Crítico, e o alvo fica incapacitadoe não pode falar e respirar até receber tratamento."
},
{
"id": 2,
"title": "mão perfurada",
"type": {
"id": 2,
"text": "perfurante",
"image": "piercing.png"
},
"description": "Danos Crítico, e o alvo solta o que estiver segurando (1 item) e não pode usar aquele membro até o início de seu próximo turno."
},
{
"id": 3,
"title": "testa cortada",
"type": {
"id": 3,
"text": "cortante",
"image": "sharp.png"
},
"description": "Danos Crítico, e o alvo fica cego até o início de seu próximo turno."
},
{
"id": 4,
"title": "vulnerabilidade mágica",
"type": {
"id": 4,
"text": "mágico",
"image": "magic.png"
},
"description": "Danos Crítico, e o alvo tem vulnerabilidade a dano mágico até o início de seu próximo turno."
}
]
}
}
Controller
package br.com.rpgnext.deck.critical.controller;
import java.beans.Transient;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import br.com.rpgnext.deck.critical.service.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import br.com.rpgnext.deck.critical.model.Card;
import br.com.rpgnext.deck.critical.model.Item;
import br.com.rpgnext.deck.critical.model.Type;
import br.com.rpgnext.deck.critical.repository.CardRespository;
import br.com.rpgnext.deck.critical.repository.ItemRepository;
import br.com.rpgnext.deck.critical.repository.TypeRepository;
import br.com.rpgnext.deck.critical.service.CardService;
@RestController
public class CardController {
@Autowired
private CardRespository cardRespository;
@Autowired
private TypeRepository typeRepository;
@Autowired
private ItemRepository itemRepository;
@Autowired
private CardService cardService;
@Autowired
private ItemService itemService;
@RequestMapping(value = "card/save", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE )
@ResponseBody
public ResponseEntity save(@RequestBody Card card){
Card cardSaved = cardRespository.save(card);
return new ResponseEntity(cardSaved, HttpStatus.CREATED);
}
@RequestMapping(value = "cards/save", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity> saveAll(@RequestBody List cards){
return new ResponseEntity((List) cardRespository.findAll(), HttpStatus.FOUND);
}
@RequestMapping(value = "cards", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity> findAll(){
return new ResponseEntity((List) cardRespository.findAll(), HttpStatus.FOUND);
}
@RequestMapping(value = "card/{id}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity findById(@PathVariable Long id){
return new ResponseEntity((cardRespository.findById(id).get()), HttpStatus.FOUND);
}
@RequestMapping(value = "card/random", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity randomCard(){
List cards = (List) cardRespository.findAll();
Card card = cardService.randomCard(cards);
return new ResponseEntity(card, HttpStatus.OK);
}
@RequestMapping(value = "card/new", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity randomNewCard(){
Card card = new Card();
for(Long i = 1L; i allItemsByType = itemRepository.findAllByType(type);
Item item = itemService.randomItem(allItemsByType);
//item.setCard(card);
//card.addItem(item);
}
Card cardSaved = cardRespository.save(card);
return new ResponseEntity(cardSaved, HttpStatus.CREATED);
}
}