【问题标题】:Spring boot entity many to one mappping in embaded object嵌入式对象中的 Spring Boot 实体多对一映射
【发布时间】:2020-08-01 14:22:33
【问题描述】:

我正在构建一个简单的 Spring Boot 博客应用程序。这个应用程序有两个实体用户和帖子。 user表保存用户数据,主键为id,post表保存内容信息,用户信息为外键“postedBy”,指的是用户表的id。一个用户可以有很多帖子。

基于此,我设计了如下所示的实体类。

@Entity
@Table
public class User {
    @Id
    @GeneratedValue(generator="system-uuid")
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    private String id;
    private String name;
    private String email;
}


@Entity
@Table
public class Post {
    @Id
    @GeneratedValue(generator="system-uuid")
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    private String id;
    private String title;
    @ManyToOne
    @JoinColumn(name = "id" , insertable = false,updatable = false)
    private User postedBy;
    private String content;
}

作为一个用户可以有多个帖子,我有用户 @ManyToOne 注释,它通过 @JoinColumn

映射到用户的 id

我正在使用 JpaRepository 接口,然后通过休息控制器公开。

但是当我发送正文插入如下帖子时

{
    "title":"The Graphql way of design",
    "postedBy":"402880ee73aa45570173aa462ea00001",
    "content":" The content of blog "
}

它抛出以下错误

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `com.graphql.blog.model.User` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('402880ee73aa45570173aa462ea00001'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.graphql.blog.model.User` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('402880ee73aa45570173aa462ea00001')
 at [Source: (PushbackInputStream); line: 3, column: 13] (through reference chain: com.graphql.blog.model.Post["postedBy"])]

我期待postedBy 列将存储“402880ee73aa45570173aa462ea00001”,因为用户已经存在,作为响应,它会发送用户详细信息,自动获取该帖子的用户详细信息。

【问题讨论】:

  • 我认为您也可以尝试在对象中添加一个新属性postedById,使用与postedBy 相同的注释,但用insertable = true, updatable = true 标记这个。这样,您可以尝试将 json 中的海报 id 发送为postedById

标签: java spring spring-boot spring-data-jpa


【解决方案1】:

您收到错误是因为字符串字段无法反序列化为 User 的对象。

我期待postedBy 列将存储 “402880ee73aa45570173aa462ea00001”因为用户已经存在并且在 响应,它将发送用户详细信息自动获取用户 该帖子的详细信息。

不,spring 不能自动执行此操作。首先通过像这样使用 json 正确反序列化 id。

{
    "title":"The Graphql way of design",
    "postedBy":{
                  "id": "402880ee73aa45570173aa462ea00001"
               },
    "content":" The content of blog "
}

然后先通过id获取User并设置在Post中,例如:

Optional<User> user = userRepository.findById(post.getPostedBy.getId());
post.setUser(user.get());

并使用@JoinColumn 作为您要在 post 表中为用户存储外键的字段。

@ManyToOne
@JoinColumn(name = "postedBy")
private User postedBy;

【讨论】:

    【解决方案2】:

    根据您的要求,您应该输入以下代码:

    在课堂上,User

    @OneToMany(mappedBy = "postedBy", cascade = CascadeType.DETACH)
    private List<Post> posts;
    

    在课堂上,Post

    @ManyToOne
    @JsonIgnore
    private User postedBy;
    

    【讨论】:

    • 我试试这个,我尝试的方式有什么问题
    • @JsonIgnore 用于避免循环引用。可以查看this了解CascadeType.DETACH
    【解决方案3】:

    User类中添加@JsonIdentityInfo注解:

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
    

    注释用于指示带注释的类型或属性的值应该被序列化,以便实例包含额外的对象标识符(除了实际的对象属性),或者作为由引用完整序列化的对象 id 组成的引用。

    【讨论】:

    • 我尝试将注释放到类级别,但收到错误 JSON 解析错误:未解析的前向引用:;嵌套异常是 com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Unresolved forward references for: at [Source: (PushbackInputStream);行:5,列:1]对象 id [402880ee73aa45570173aa462ea00001](for com.graphql.blog.model.User)在 [Source: (PushbackInputStream);行:3,列:47]。]
    猜你喜欢
    • 2021-09-15
    • 2017-02-17
    • 2020-11-17
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多