使用JPA关系映射的Spring数据Rest测试:带有更新的奇怪行为

使用JPA关系映射的Spring数据Rest测试:带有更新的奇怪行为,jpa,spring-boot,spring-data-rest,Jpa,Spring Boot,Spring Data Rest,我遵循本教程()来试验Spring数据REST,我想用TestRestTemplate测试CRUD 添加(postForEntity)是可以的 删除(Delete)是可以的 读取(getForEntity)是可以的 更新(template.exchange(URL,HttpMethod.PUT,entity,String.class,ID))仅在我与其他实体没有任何关系时有效。。。我不明白为什么 下面是一个例子: @Data @Entity public class Dojo {

我遵循本教程()来试验Spring数据REST,我想用
TestRestTemplate
测试CRUD

  • 添加(postForEntity)是可以的
  • 删除(Delete)是可以的
  • 读取(getForEntity)是可以的
  • 更新(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;
    }
}
所以基本上,我没有在我的对象中改变任何东西,但是

  • 结果代码是200
  • 它改变了我的对象的属性
  • 名称被修改为dojo.name值 只是。。。为什么?

    更多信息:

    • 当我用一个新名称(使用newValue;-)创建一个新的workshop对象和一个新的Dojo并尝试更新现有workshop时,结果仍然是一样的。workshop.dojo未更改,名称从dojo.name复制。所以基本上,我的更新不起作用
    • 我还尝试使用
      mockMvc
      ,而不是像这样使用
      testrestemplate

      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)时,返回一个geton-localhost:8080/api/workshop/1

      {
        "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)的正确方法是什么
    • 测试此更新的正确方法是什么

    谢谢大家,祝你们今天愉快!:-)

    我想这是因为你们在使用联想。在这种情况下,您必须自己提供实体的链接/取消链接。例如,在集合setter中,如下所示:

    @数据
    @ToString(exclude=“slaves”)
    @实体
    公共班主任{
    @身份证
    @生成值
    私人长id;
    私有字符串名称;
    @OneToMany(mappedBy=“master”,cascade={PERSIST,MERGE})
    私人名单奴隶;
    公共void setslave(列出从属){
    //将新从属链接到此主节点
    slaves.forEach(slave->slave.setMaster(this));
    //取消链接上一个从机
    如果(this.slaves!=null)this.slaves.forEach(slave->slave.setMaster(null));
    这个。奴隶=奴隶;
    }
    }
    @资料
    @实体
    公营奴隶{
    @身份证
    @生成值
    私人长id;
    私有字符串名称;
    @许多酮
    私人硕士;
    }
    
    然后您可以存储
    从机

    POST http://localhost:8080/api/slaves
    {
        "name": "slave1"
    }
    
    // the same for salve2, slave3, slave4
    
    PUT http://localhost:8080/api/slaves/1
    {
        "name": "slave1u", 
        "master": "http://localhost:8080/api/masters/2"
    }
    
    PUT http://localhost:8080/api/slaves/2
    {
        "name": "slave2u", 
        "master": "http://localhost:8080/api/masters/2"
    }
    
    存储
    Master

    POST http://localhost:8080/api/masters
    {
        "name": "master1", 
        "slaves": [
            "http://localhost:8080/api/slaves/1",
            "http://localhost:8080/api/slaves/2"
            ]
    }
    
    PUT http://localhost:8080/api/masters/1
    {
        "name": "master1u", 
        "slaves": [
            "http://localhost:8080/api/slaves/3",
            "http://localhost:8080/api/slaves/4"
            ]
    }
    
    PUT http://localhost:8080/api/masters/2
    {
        "name": "master2"
    }
    
    更新
    Master

    POST http://localhost:8080/api/masters
    {
        "name": "master1", 
        "slaves": [
            "http://localhost:8080/api/slaves/1",
            "http://localhost:8080/api/slaves/2"
            ]
    }
    
    PUT http://localhost:8080/api/masters/1
    {
        "name": "master1u", 
        "slaves": [
            "http://localhost:8080/api/slaves/3",
            "http://localhost:8080/api/slaves/4"
            ]
    }
    
    PUT http://localhost:8080/api/masters/2
    {
        "name": "master2"
    }
    
    或更新
    从机

    POST http://localhost:8080/api/slaves
    {
        "name": "slave1"
    }
    
    // the same for salve2, slave3, slave4
    
    PUT http://localhost:8080/api/slaves/1
    {
        "name": "slave1u", 
        "master": "http://localhost:8080/api/masters/2"
    }
    
    PUT http://localhost:8080/api/slaves/2
    {
        "name": "slave2u", 
        "master": "http://localhost:8080/api/masters/2"
    }
    
    见工作


    另外

    谢谢。我使用curl命令得到了正确的结果。但我尝试使用TestRestTemplate进行的测试仍然不正确:/