#java #spring-boot #spring-mvc #jackson #spring-data
#java #spring-boot #spring-mvc #джексон #spring-данные
Вопрос:
Итак, я внедряю API с использованием springboot, spring-data и Jackson, но у меня возникают некоторые проблемы, когда я пытаюсь отправить запрос на конечную точку, у которой есть двунаправленная связь @OneToMany.
У меня не так много опыта, поэтому мне действительно нужна помощь.
У меня есть две сущности:
Partida
package lucas.duarte.jazz.model.bean;
import java.io.Serializable;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
@Entity
public class Partida implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String timeA;
private String timeB;
private boolean visitante;
@OneToMany(mappedBy = "partida", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Set> sets;
public List<Set> getSets() {
return sets;
}
public void setSets(List<Set> sets) {
this.sets = sets;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTimeA() {
return timeA;
}
// Mocado o valor pois o Time A sempre e a Sao Judas
public void setTimeA(String timeA) {
this.timeA = timeA;
}
public String getTimeB() {
return timeB;
}
public void setTimeB(String timeB) {
this.timeB = timeB;
}
public boolean isVisitante() {
return visitante;
}
public void setVisitante(boolean visitante) {
this.visitante = visitante;
}
}
и УСТАНОВИТЬ
package lucas.duarte.jazz.model.bean;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@Entity
@Table(name = "meu_set")
public class Set implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "ponto_a")
private long pontoA;
@Column(name = "ponto_b")
private long pontoB;
@Column(name = "set_finalizado")
private boolean setFinalizado;
@ManyToOne
@JoinColumn(name = "partida_id")
private Partida partida;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public long getPontoA() {
return pontoA;
}
public void setPontoA(long pontoA) {
this.pontoA = pontoA;
}
public long getPontoB() {
return pontoB;
}
public void setPontoB(long pontoB) {
this.pontoB = pontoB;
}
public boolean isSetFinalizado() {
return setFinalizado;
}
public void setSetFinalizado(boolean setFinalizado) {
this.setFinalizado = setFinalizado;
}
public Partida getPartida() {
return partida;
}
public void setPartida(Partida partida) {
this.partida = partida;
}
}
Это мой SetControler
package lucas.duarte.jazz.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
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.util.UriComponentsBuilder;
import lucas.duarte.jazz.model.bean.Set;
import lucas.duarte.jazz.model.service.SetService;
@Controller
@RequestMapping("/api")
public class SetController {
private SetService setServ;
@RequestMapping(value = "/set/", method = RequestMethod.POST)
public ResponseEntity<?> salvarSet(@RequestBody Set set, UriComponentsBuilder ucBuilder) {
System.out.println("Vou cadastrar um set vinculado a uma partida");
System.out.println(set.getPartida().getId());
setServ.salvarSet(set);
return new ResponseEntity(HttpStatus.CREATED);
}
}
Когда я ОТПРАВЛЯЮ сообщение по URL, я получаю следующий результат
{
"timestamp": "2019-03-28T04:17:46.857 0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Cannot construct instance of `lucas.duarte.jazz.model.bean.Partida` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `lucas.duarte.jazz.model.bean.Partida` (although at least one Creator exists): no int/Int-argument constructor/factory method to deserialize from Number value (1)n at [Source: (PushbackInputStream); line: 5, column: 14] (through reference chain: lucas.duarte.jazz.model.bean.Set["partida"])",
"path": "/api/set/"
}
У меня уже есть Partida в моей базе данных, но я не могу опубликовать этот метод, мне действительно нужна помощь.
Комментарии:
1. пожалуйста, определите общедоступную часть конструктора по умолчанию (){}
2. В целях десериализации класс Partida должен иметь конструктор с нулевым аргументом.
3. Покажите тело json, которое вы пытаетесь отправить в эту конечную точку
4.
{ "pontoA" : 1, "pontoB" : 1, "setFinalizado" : "false", "partida_id" : 1 }
Тело моего запроса в формате Json5. @LucasDuarte попробуйте это { «partida_id»: 1, «pontoA»: 1, «pontoB»: 1, «setFinalizado»: «false»}
Ответ №1:
Эта проблема не имеет ничего общего с двунаправленным отображением JPA. Это ошибка, возникающая во время де сериализации.
У Partida -> должен быть конструктор с нулевым аргументом
Полезная нагрузка запроса должна иметь { «partida»:{«id»:123}}, чтобы заполнить свойство объекта partida.
Комментарии:
1. Когда я попробовал это, я получил следующую 2019-03-28 02:48:17.679 ОШИБКУ 8180 — [nio-5888-exec-3] o.a.c.c.C.[.[.[/].[ DispatcherServlet] : Servlet.service() для сервлета [DispatcherServlet] в контексте с path [] выдал исключение [Ошибка обработки запроса; вложенным исключением является java.lang. Исключение NullPointerException] с основной причиной
2. Вы были правы, именно так, кому я передаю JSON, и выполнение нулевого указателя было вызвано тем, что я забыл аннотацию @Autowired, чтобы ввести зависимость.
3. Это хорошая новость, по крайней мере, ошибка json устранена. private SetService setServ; имеет значение null, и любая операция в объекте вызовет исключение нулевого указателя.
Ответ №2:
для получения подробной информации проверьте эту ссылку на Jackson library.
@Entity
public class Partida implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String timeA;
private String timeB;
private boolean visitante;
public Partida(){
//Default constructor required here
}
@OneToMany(mappedBy = "partida", fetch = FetchType.LAZY, cascade =
CascadeType.ALL)
private List<Set> sets;
public List<Set> getSets() {
return sets;
}
public void setSets(List<Set> sets) {
this.sets = sets;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTimeA() {
return timeA;
}
// Mocado o valor pois o Time A sempre e a Sao Judas
public void setTimeA(String timeA) {
this.timeA = timeA;
}
public String getTimeB() {
return timeB;
}
public void setTimeB(String timeB) {
this.timeB = timeB;
}
public boolean isVisitante() {
return visitante;
}
public void setVisitante(boolean visitante) {
this.visitante = visitante;
}
}
если проблема не решена, попробуйте JSON creator
@JsonCreator
public Partida(@JsonProperty("id") Long id, @JsonProperty("timeA") String
timeA, @JsonProperty("timeB") String timeB, @JsonProperty("desc") boolean
visitante) {
this.id = id;
this.timeA = timeA;
this.timeB= timeB;
this.visitante= visitante;
}
Комментарии:
1. Это не работает одновременно, я пробовал с пустым конструктором и с аннотацией @JsonCreator, сервер всегда выдает одну и ту же ошибку
2. @LucasDuarte: создайте пустой конструктор в вашем классе set public Set(){} и после этого поделитесь своим сообщением об ошибке