【发布时间】:2023-03-17 23:47:01
【问题描述】:
我按照本教程 (https://spring.io/guides/tutorials/react-and-spring-data-rest/#react-and-spring-data-rest-part-5) 来试验 Spring Data REST,我想用 TestRestTemplate 测试 CRUD。
- 添加(postForEntity)没问题。
- delete(删除)就ok了。
- 读取 (getForEntity) 没问题。
- Update (template.exchange(URL, HttpMethod.PUT, entity, String.class, ID)) 仅在我与其他实体没有任何关系时才有效...我不明白为什么。李>
这是一个例子:
@Data
@Entity
public class Dojo {
private @Id @GeneratedValue Long id;
private String name;
private String location;
private Date created;
@OneToMany(mappedBy = "dojo")
@JsonIgnore
private List<Workshop> workshops;
private Dojo() {}
public Dojo(String name, String location) {
this.name = name;
this.location = location;
this.created = new Date();
this.workshops = new ArrayList<>();
}
//getters and setters ...
}
@Data
@Entity
public class Workshop {
private @Id @GeneratedValue Long id;
private String name;
@ManyToOne
private Dojo dojo;
private Workshop() {}
public Workshop(String name, Dojo dojo) {
this.name = name;
this.dojo = dojo;
}
}
所以,我在 Dojo 和 Workshop 之间有一个双向的 1:n 关系。 @JsonIgnore 注释在这里是为了避免 JSON Marshaller 的无限循环。 存储库是标准的
public interface WorkshopRepository extends CrudRepository<Workshop, Long> {}
现在我的测试:我想更新一个研讨会。听起来不错,但不起作用。
@Test
public void testUpdateWorkshop() throws Exception {
final String DOJO_NAME="My Dojo";
final String DOJO_LOCATION="Liege";
final String WORKSHOP_NAME="Stuff";
final String HOST_PORT="http://localhost:8080";
//creation of a dojo
final Dojo DOJO = dojoRep.save(new Dojo(DOJO_NAME,DOJO_LOCATION));
//creation of a workshop
Workshop workshop = workshopRep.save(new Workshop(WORKSHOP_NAME,DOJO));
String newValue = "After Test";
System.out.println("before update");
System.out.println(workshop.getName()+" == "+WORKSHOP_NAME);
Long oldID = workshop.getId();
//As you can see I didn't modify the workshop object
HttpEntity<Workshop> entity = new HttpEntity<Workshop>(workshop);
ResponseEntity<String> response = template.exchange(HOST_PORT+"/api/workshops/"+oldID, HttpMethod.PUT, entity, String.class, oldID);
assert response.getStatusCodeValue() == 200;
//re-Get the updated workshop
workshop = workshopRep.findOne(oldID);
System.out.println("after update");
System.out.println(workshop.getName()+" == "+WORKSHOP_NAME);
// as I didn't set the newValue, it must fail and workshop.getName() must stay equal to "Stuff".
Assert.assertEquals("Update does not work",newValue,workshop.getName());
}
我运行mvn clean test 和
before update
Stuff == Stuff
after update
My Dojo == Stuff
Failed tests:
WorkshopTests.testUpdateWorkshop:218 Update not work expected:<[After Test]> but was:<[My Dojo]>
所以基本上,我没有对我的对象进行任何更改,但是
- 结果代码为 200。
- 它改变了我的对象的一个属性。
- 名称已修改为采用 dojo.name 值!
只是……为什么?
更多信息:
- 当我使用新名称(使用 newValue ;-))和新的 Dojo 创建一个新的工作室对象并尝试更新现有的工作室时,结果仍然相同。 Workshop.dojo 未更改,名称从 dojo.name 复制。所以基本上,我的更新不起作用。
-
我也尝试使用
mockMvc,而不是像这样的TestRestTemplate。mockMvc.perform(put(HOST_PORT+"/api/workshops/"+oldID) .contentType(MediaType.APPLICATION_JSON_UTF8) .content(convertObjectToJsonBytes(workshop)) );用函数
private byte[] convertObjectToJsonBytes(Object object) throws IOException { ObjectMapper mapper = new ObjectMapper(); System.out.println("log my face "); System.out.println(mapper.writeValueAsString(object)); return mapper.writeValueAsBytes(object); }并且日志似乎在更新之前正确解析了我的对象...
{"id":1,"name":"Stuff","dojo":{"id":1,"name":"My Dojo","location":"Liege","created":1500799092330}}但还是不行:(
-
当我运行应用程序 (mvn spring-boot:run) 时,localhost:8080/api/workshops/1 上的 GET 会返回
{ "name" : "Stuff", "_links" : { "self" : { "href" : "http://localhost-core:8080/api/workshops/1" }, "workshop" : { "href" : "http://localhost-core:8080/api/workshops/1" }, "dojo" : { "href" : "http://localhost-core:8080/api/workshops/1/dojo" } } } - 如果我通过 nameD 更改我的 Dojo 类的属性名称并使用新名称和新 Dojo(之前保存到 DB 中)进行更新,则名称会更新,但不会更新 dojo。
总结一下我的问题是:
- 只是……为什么?
- 使用 HTTP 请求更新像 Workshop 这样的对象的正确方法是什么?
- 测试此更新的正确方法是什么?
谢谢大家,祝你有美好的一天! :-)
【问题讨论】:
标签: jpa spring-boot spring-data-rest