【发布时间】:2014-10-15 18:44:19
【问题描述】:
我有两个课程:Course 和 Lesson。课程是@OneToMany 与课程的关系。使用 Spring Boot,我创建了一个简单的 REST API 来管理类。我已经用邮递员手动测试了 API,看起来一切正常。
接下来,我编写了简单的 JUnite 来自动测试 API。测试完成后,课程实体已正确保存在数据库中,但课程抛出错误:
2014-10-15 20:19:15.162 错误 5812 --- [nio-8080-exec-2] s.d.r.w.AbstractRepositoryRestController:无法读取 JSON:模板不能为空或为空! (通过参考链:com.mbury.elearning.domain.Lesson["course"]);嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:模板不能为空或为空! (通过参考链:com.mbury.elearning.domain.Lesson["course"])
看起来@OneToMany 关系未正确映射,但我不知道如何处理。有谁知道如何使用包含子对象的实体配置 Spring REST 以正常工作?
下面我附上了我所有的代码:
LessonTest.java
package com.mbury.elearning;
import static org.hamcrest.Matchers.equalTo;
import static org.springframework.test.util.MatcherAssertionErrors.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.boot.test.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;
import com.mbury.elearning.domain.Course;
import com.mbury.elearning.domain.Lesson;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
public class LessonTest {
final String BASE_URL_COURSE = "http://localhost:8080/courses/";
final String BASE_URL_LESSON = "http://localhost:8080/lessons/";
@Test
public void shouldCreateNewLesson() {
final String COURSE_TITLE = "test";
final String COURSE_DESCRIPTION = "test";
final String LESSON_TOPIC = "test";
Course course = new Course();
course.setTitle(COURSE_TITLE);
course.setDescription(COURSE_DESCRIPTION);
Lesson lesson = new Lesson();
lesson.setTopic(LESSON_TOPIC);
lesson.setCourse(course);
RestTemplate rest = new TestRestTemplate();
ResponseEntity<Course> response = rest.postForEntity(BASE_URL_COURSE, course,
Course.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.CREATED));
ResponseEntity<Lesson> response1 = rest.postForEntity(BASE_URL_LESSON, lesson,
Lesson.class);
assertThat(response1.getStatusCode(), equalTo(HttpStatus.CREATED));
}
}
Course.java
package com.mbury.elearning.domain;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "course")
public class Course {
@Column(name = "description")
private String description;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Integer id;
@OneToMany(mappedBy = "course")
private List<Lesson> lesson;
@Column(name = "title")
private String title;
public String getDescription() {
return description;
}
public Integer getId() {
return id;
}
public List<Lesson> getLesson() {
return lesson;
}
public String getTitle() {
return title;
}
public void setDescription(String description) {
this.description = description;
}
public void setId(Integer id) {
this.id = id;
}
public void setLesson(List<Lesson> lesson) {
this.lesson = lesson;
}
public void setTitle(String title) {
this.title = title;
}
}
Lesson.java
package com.mbury.elearning.domain;
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;
@Entity
@Table(name = "lesson")
public class Lesson {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private int id;
@Column(name = "topic")
private String topic;
@ManyToOne(optional = false)
@JoinColumn(name = "ID_COURSE")
Course course;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public Course getCourse() {
return course;
}
public void setCourse(Course course) {
this.course = course;
}
}
CourseRepository.java
package com.mbury.elearning.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.mbury.elearning.domain.Course;
@RepositoryRestResource
public interface CourseRepository extends CrudRepository<Course, Integer> {
}
LessonRepository .java
package com.mbury.elearning.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import com.mbury.elearning.domain.Lesson;
@RepositoryRestResource
public interface LessonRepository extends CrudRepository<Lesson, Integer> {
}
应用程序.java
package com.mbury.elearning;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
@Configuration
@ComponentScan
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
【问题讨论】:
-
我知道,如果您发布此内容,
{"id":0,"topic":"test","course":"http://localhost:8080/courses/1"}它应该会为您生成课程。但是我不确定如何使用RestTemplate生成这种请求。这似乎是一个相关问题 - stackoverflow.com/questions/24356680/cant-post-a-collection -
@BijuKunjummen 当我说手动测试 REST API 时,我的意思是发布内容。它工作正常。现在我只想从 JUint 做。没有必要使用 RestTemplate。
标签: spring spring-boot spring-data-jpa spring-data-rest spring-test