【发布时间】:2017-05-10 05:11:33
【问题描述】:
我有一个数据库,其中有一个名为 person 的表:
id | first_name | last_name | date_of_birth
----|------------|-----------|---------------
1 | Tin | Tin | 2000-10-10
有一个名为 Person 的 JPA 实体映射到此表:
@Entity
@XmlRootElement(name = "person")
@XmlAccessorType(NONE)
public class Person {
@Id
@GeneratedValue
private Long id;
@XmlAttribute(name = "id")
private Long externalId;
@XmlAttribute(name = "first-name")
private String firstName;
@XmlAttribute(name = "last-name")
private String lastName;
@XmlAttribute(name = "dob")
private String dateOfBirth;
// setters and getters
}
该实体还使用 JAXB 注释进行注释,以允许 XML 有效负载 要映射到实体实例的 HTTP 请求。
我想实现一个端点来检索和更新具有给定id 的实体。
根据this answer to a similar question, 我需要做的就是实现 handler 方法如下:
@RestController
@RequestMapping(
path = "/persons",
consumes = APPLICATION_XML_VALUE,
produces = APPLICATION_XML_VALUE
)
public class PersonController {
private final PersonRepository personRepository;
@Autowired
public PersonController(final PersonRepository personRepository) {
this.personRepository = personRepository;
}
@PutMapping(value = "/{person}")
public Person savePerson(@ModelAttribute Person person) {
return personRepository.save(person);
}
}
但是,这并没有按预期工作,可以通过以下失败的测试用例进行验证:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class PersonControllerTest {
@Autowired
private TestRestTemplate restTemplate;
private HttpHeaders headers;
@Before
public void before() {
headers = new HttpHeaders();
headers.setContentType(APPLICATION_XML);
}
// Test fails
@Test
@DirtiesContext
public void testSavePerson() {
final HttpEntity<Object> request = new HttpEntity<>("<person first-name=\"Tin Tin\" last-name=\"Herge\" dob=\"1907-05-22\"></person>", headers);
final ResponseEntity<Person> response = restTemplate.exchange("/persons/1", PUT, request, Person.class, "1");
assertThat(response.getStatusCode(), equalTo(OK));
final Person body = response.getBody();
assertThat(body.getFirstName(), equalTo("Tin Tin")); // Fails
assertThat(body.getLastName(), equalTo("Herge"));
assertThat(body.getDateOfBirth(), equalTo("1907-05-22"));
}
}
第一个断言失败:
java.lang.AssertionError:
Expected: "Tin Tin"
but: was "Tin"
Expected :Tin Tin
Actual :Tin
换句话说:
- 没有出现服务器端异常(状态码为
200) - Spring 成功加载了带有
id=1的 Person 实例 - 但其属性未更新
任何想法我在这里错过了什么?
注 1
here 提供的解决方案不起作用。
注2
提供了演示问题的完整工作代码 here.
更多详情
预期行为:
- 使用
id=1加载Person 实例 - 使用
Jaxb2RootElementHttpMessageConverter或MappingJackson2XmlHttpMessageConverter使用XML 有效负载填充已加载人员实体的属性 - 将其作为
person参数传递给控制器的操作处理程序
实际行为:
-
id=1的 Person 实例已加载 - 实例的属性未更新以匹配请求负载中的 XML
- 传递给控制器的操作处理程序方法的人员实例的属性未更新
【问题讨论】:
-
它是如何失败的?响应实际上包含什么?它是否将人保存在数据库中?当您使用调试器并查看会发生什么时会发生什么?您需要阅读错误消息并进行调查。
-
有人投票关闭它,因为它没有编程!开什么玩笑。
-
别人问了你一些问题。
-
我已经回答了他(在问题的最底部)。我还提供了完整的源代码以及演示该问题的集成测试。
-
我在更多详情部分添加了更多信息。如果您需要更多详细信息,请告诉我。
标签: spring spring-mvc spring-boot spring-data-jpa