[SPRING] 스프링 데이터 REST로 중첩 된 엔티티를 POST하는 방법
SPRING스프링 데이터 REST로 중첩 된 엔티티를 POST하는 방법
나는 Spring Data REST 애플리케이션을 만들고 있는데 POST 할 때 몇 가지 문제가있다. 주체에는 다른 두 개의 관련 엔티티가 중첩되어 있습니다.
많은 답변을 가진 "질문"객체가 있으며이 답변 중 많은 답변이 많습니다.
나는 앞의 애플리케이션에서 설문지를 POST하기 위해 JSON을 생성한다.
{
"user": "http://localhost:8080/users/1",
"status": 1,
"answers": [
{
"img": "urlOfImg",
"question": "http://localhost:8080/question/6",
"replies": [
{
"literal": "http://localhost:8080/literal/1",
"result": "6"
},
{
"literal": "http://localhost:8080/literal/1",
"result": "6"
}
]
},
{
"img": "urlOfImg",
"question": "http://localhost:8080/question/6",
"replies": [
{
"literal": "http://localhost:8080/literal/3",
"result": "10"
}
]
}
]
}
하지만 게시하려고하면 다음과 같은 오류 응답이 나타납니다.
{
"cause" : {
"cause" : {
"cause" : null,
"message" : "Template must not be null or empty!"
},
"message" : "Template must not be null or empty! (through reference chain: project.models.Questionary[\"answers\"])"
},
"message" : "Could not read JSON: Template must not be null or empty! (through reference chain: project.models.Questionary[\"answers\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Template must not be null or empty! (through reference chain: project.models.Questionary[\"answers\"])"
}
편집하다:
내 저장소도 추가합니다.
@RepositoryRestResource(collectionResourceRel = "questionaries", path = "questionaries")
public interface InspeccionRepository extends JpaRepository<Inspeccion, Integer> {
@RestResource(rel="byUser", path="byUser")
public List<Questionary> findByUser (@Param("user") User user);
}
My Entity Question 강의는 다음과 같습니다.
@Entity @Table(name="QUESTIONARY", schema="enco" )
public class Questionary implements Serializable {
private static final long serialVersionUID = 1L;
//----------------------------------------------------------------------
// ENTITY PRIMARY KEY ( BASED ON A SINGLE FIELD )
//----------------------------------------------------------------------
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEC_QUESTIONARY")
@SequenceGenerator(name = "SEC_QUESTIONARY", sequenceName = "ENCO.SEC_QUESTIONARY", allocationSize = 1)
@Column(name="IDQUES", nullable=false)
private Integer idques ;
//----------------------------------------------------------------------
// ENTITY DATA FIELDS
//----------------------------------------------------------------------
@Column(name="ESTATUS")
private Integer estatus ;
//----------------------------------------------------------------------
// ENTITY LINKS ( RELATIONSHIP )
//----------------------------------------------------------------------
@ManyToOne
@JoinColumn(name="IDUSER", referencedColumnName="IDUSER")
private User user;
@OneToMany(mappedBy="questionary", targetEntity=Answer.class)
private List<Answer> answers;
//----------------------------------------------------------------------
// CONSTRUCTOR(S)
//----------------------------------------------------------------------
public Questionary()
{
super();
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR FIELDS
//----------------------------------------------------------------------
//--- DATABASE MAPPING : IDNSE ( NUMBER )
public void setIdnse( Integer idnse )
{
this.idnse = idnse;
}
public Integer getIdnse()
{
return this.idnse;
}
//--- DATABASE MAPPING : ESTADO ( NUMBER )
public void setEstatus Integer estatus )
{
this.estatus = estatus;
}
public Integer getEstatus()
{
return this.estatus;
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR LINKS
//----------------------------------------------------------------------
public void setUser( Usuario user )
{
this.user = user;
}
public User getUser()
{
return this.user;
}
public void setAnswers( List<Respuesta> answers )
{
this.answers = answer;
}
public List<Answer> getAnswers()
{
return this.answers;
}
// Get Complete Object method public List<Answer>
getAnswerComplete() {
List<Answer> answers = this.answers;
return answers;
}
}
내 답변 엔티티 :
@Entity @Table(name="ANSWER", schema="enco" ) public class Answer
implements Serializable {
private static final long serialVersionUID = 1L;
//----------------------------------------------------------------------
// ENTITY PRIMARY KEY ( BASED ON A SINGLE FIELD )
//----------------------------------------------------------------------
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEC_ANSWER")
@SequenceGenerator(name = "SEC_ANSWER", sequenceName = "ENCOADMIN.SEC_ANSWER", allocationSize = 1)
@Column(name="IDANS", nullable=false)
private Integer idans ;
//----------------------------------------------------------------------
// ENTITY DATA FIELDS
//----------------------------------------------------------------------
@Column(name="IMG", length=100)
private String img ;
//----------------------------------------------------------------------
// ENTITY LINKS ( RELATIONSHIP )
//----------------------------------------------------------------------
@ManyToOne
@JoinColumn(name="IDQUES", referencedColumnName="IDQUES")
private Questionary questionary ;
@OneToMany(mappedBy="answer", targetEntity=Reply.class)
private List<Reply> replies;
@ManyToOne
@JoinColumn(name="IDQUE", referencedColumnName="IDQUE")
private Question Question ;
//----------------------------------------------------------------------
// CONSTRUCTOR(S)
//----------------------------------------------------------------------
public Answer()
{
super();
}
//----------------------------------------------------------------------
// GETTER & SETTER FOR THE KEY FIELD
//----------------------------------------------------------------------
public void setIdans( Integer idans )
{
this.idans = idans ;
}
public Integer getIdans()
{
return this.idans;
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR FIELDS
//----------------------------------------------------------------------
//--- DATABASE MAPPING : IMAGEN ( VARCHAR2 )
public void setImg( String img )
{
this.img = img;
}
public String getImg()
{
return this.img;
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR LINKS
//----------------------------------------------------------------------
public void setQuestionary( Questionary questionary )
{
this.questionary = questionary;
}
public Questionary getQuestionary()
{
return this.questionary;
}
public void setReplies( List<Reply> contestaciones )
{
this.replies = replies;
}
public List<Reply> getReplies()
{
return this.replies;
}
public void setQuestion( Question question )
{
this.question = question;
}
public Question getQuestion()
{
return this.question;
}
}
그리고 이것은 오류 콘솔입니다.
Caused by: com.fasterxml.jackson.databind.JsonMappingException:
Template must not be null or empty! (through reference chain:
project.models.Questionary["answers"]) at
com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
~[jackson-databind-2.3.3.jar:2.3.3] at *snip*
해결법
-
==============================
1.Questionnaire 클래스의 필드 응답에 @RestResource (exported = false)를 추가하십시오.
Questionnaire 클래스의 필드 응답에 @RestResource (exported = false)를 추가하십시오.
내 말에 따르면,이 오류는 JSON에 응답을 중첩하는 대신 URI가 응답을 가져올 것으로 예상하기 때문에 디시리얼라이저가 발생하기 때문에 발생합니다. 주석을 추가하면 JSON을 대신 보게됩니다.
-
==============================
2.2.3.0.M1에서이 오류가 계속 표시되지만 해결 방법을 찾았습니다.
2.3.0.M1에서이 오류가 계속 표시되지만 해결 방법을 찾았습니다.
기본 문제는 다음과 같습니다. JSON에 포함 된 엔티티의 URL을 게시하면 작동합니다. 실제 포함 된 엔티티 JSON을 게시하면 그렇지 않습니다. 엔티티 JSON을 URI로 역 직렬화하려고 시도하지만 당연히 실패합니다.
이 문제는 스프링 데이터 나머지가 해당 구성 (RepositoryRestMvcConfiguration.defaultMessageConverters ())에서 생성하는 두 개의 TypeConstrainedMappingJackson2HttpMessageConverter 객체 인 것 같습니다.
마지막으로 messageConverters의 지원되는 미디어 유형을 구성하여이 두 가지를 건너 뛰고 중첩 된 엔티티에서 올바르게 작동하는 일반 MappingJackson2HttpMessageConverter를 히트하도록 문제를 해결했습니다.
예를 들어 RepositoryRestMvcConfiguration을 확장하고이 메서드를 추가하면 content-type이 'application / json'인 요청을 보내면 URI로 역 직렬화하지 않고 일반 MappingJackson2HttpMessageConverter에 도달합니다.
@Override public void configureHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) { ((MappingJackson2HttpMessageConverter) messageConverters.get(0)) .setSupportedMediaTypes(asList(MediaTypes.HAL_JSON)); ((MappingJackson2HttpMessageConverter) messageConverters.get(2)) .setSupportedMediaTypes(asList(MediaType.APPLICATION_JSON)); }
이는 RepositoryRestMvcConfiguration에서 defaultMessageConverters ()가 생성 한 메시지 변환기를 구성합니다.
평범한 objectMapper는 JSON의 URI를 처리 할 수 없다는 것을 명심하십시오. 임베디드 엔티티의 URI를 전달할 때마다 미리 구성된 두 개의 메시지 변환기 중 하나에 도달해야합니다.
-
==============================
3.JSON의 한 가지 문제점은 문자열을 질문으로 역 직렬화하려고한다는 것입니다.
JSON의 한 가지 문제점은 문자열을 질문으로 역 직렬화하려고한다는 것입니다.
"question": "http://localhost:8080/question/6"
Answer 개체에서 Jackson은 질문 용 개체를 기다리고 있습니다. ID 대신 URL을 사용하고있는 것으로 보입니다. 문자열 대신 다음과 같이 질문에 전달해야합니다.
"question": { "id": "http://localhost:8080/question/6" }
-
==============================
4."Spring Boot Data REST Starter"라이브러리를 업데이트하십시오. 나를 위해 일했다.
"Spring Boot Data REST Starter"라이브러리를 업데이트하십시오. 나를 위해 일했다.
from https://stackoverflow.com/questions/24569399/how-to-post-nested-entities-with-spring-data-rest by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 프로파일을 이용한 Spring 통합 테스트 (0) | 2019.01.10 |
---|---|
[SPRING] Spring - 프로그래밍 방식으로 콩 세트 생성 (0) | 2019.01.10 |
[SPRING] 어노테이션을 사용하여 RestTemplate을 자동 작성하는 방법 (0) | 2019.01.10 |
[SPRING] 스프링 3에서 자동 삽입 된 키 얻기 / PostgreSQL 8.4.9 (0) | 2019.01.10 |
[SPRING] Sun JSTL taglib 선언이 "태그 라이브러리 설명자를 찾을 수 없습니다"와 함께 실패합니다 [duplicate] (0) | 2019.01.10 |