代码之家  ›  专栏  ›  技术社区  ›  Roman Kurbanov

如何创建具有关联的新实体

  •  0
  • Roman Kurbanov  · 技术社区  · 6 年前

    在这些下拉列表中,用户可以选择 选项 链接到 实体

    下拉列表包含一些标签和指向相应标签的链接 作为一个 价值 . 然后在POST请求中将该值传递给 分页和排序存储库

    必须 与其中一个办事处(也是一个实体)关联:

    @Data
    @Builder
    @Entity
    @NoArgsConstructor
    @AllArgsConstructor
    @Table(name="users")
    public class User{
    
    @Id
    @Coluemn(name="USER_ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long userId;
    
    @Column(name="USER_NAME", nullable=false)
    private String userName;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="OFFICE_ID", **nullable=false**)
    private Office office;
    }
    

    我的第一个猜测是: 邮递 -请求 http://localhost:8080/api/users/ :'application/json'

    {"userName":"Anton","office":"http://localhost:8080/api/offices/1"}
    

    {
    "cause": {
        "cause": null,
        "message": "Cannot construct instance of `test.domain.Office` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('http://localhost:8080/api/offices/1')\n at [Source: (org.apache.catalina.connector.CoyoteInputStream); line: 1, column: 160] (through reference chain: test.domain.User[\"office\"])"
    },
    "message": "JSON parse error: Cannot construct instance of `test.domain.Office` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('http://localhost:8080/api/offices/1'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `test.domain.Office` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('http://localhost:8080/api/office/1')\n at [Source: (org.apache.catalina.connector.CoyoteInputStream); line: 1, column: 160] (through reference chain: test.domain.User[\"office\"])"
    }
    

    我做错了什么?

    2 回复  |  直到 6 年前
        1
  •  0
  •   Dean    6 年前

    您正在以字符串形式发送URL资源来代替JSON对象,并期望Spring和jackson之间会发生一些神奇的事情来查找该值。当然,这不是正在发生的事情,Jackson正在尝试将URL的字符串值绑定到Office字段。这当然会失败,因为它不知道如何从字符串创建Office对象。

    一种可能的解决方案是区分实体对象(表示数据库表的实体对象)和DTO(数据传输对象),因为DTO表示与客户机的合同。执行此操作时,您可能会收到如下用户对象:

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class User{
    
      private Long userId;
    
      private String userName;
    
      private Long officeId;
    
    }
    

    现在,您只需发送一个office id而不是URL,并在代码中使用Spring数据存储库来查找office对象。然后,您可以像上面显示的那样构造实体用户对象并将其持久化。

        2
  •  0
  •   Roman Kurbanov    6 年前

    原来是因为我使用了Lombok,它生成了自己的构造函数。

    @AllArgsConstructor(suppressConstructorProperties = true)

    现在它如我所料工作:

    要发送到的Json http://localhost:8080/api/users :

    { "userName":"Anton", "office":"http://localhost:8080/api/offices/1" }

    返回:

    { "userName":"Anton", "_links": { "self": { "href": "http://localhost:8080/api/users/28" }, "user": { "href": "http://localhost:8080/api/users/28" }, "office": { "href": "http://localhost:8080/api/users/28/office" } } }