【问题标题】:many-to-many mapping with extra column - how to set mapping and how to serialise?带有额外列的多对多映射 - 如何设置映射以及如何序列化?
【发布时间】:2020-09-08 20:28:13
【问题描述】:

我是 Hibernate 的新手,我正在尝试解决类似于 this question 的问题,特别是 the answer

我有一些非常相似的设置(在我的例子中是AuthorBook 和映射表AuthorBook)。我在 Spring Data JPA 中使用它,所以我有以下组件:

  • 存储库:AuthorRepositoryBookRepositoryAuthorBookRepository
  • 服务:AuthorServiceBookServiceAuthorBookRepository
  • 控制器:AuthorControllerBookControllerAuthorBookController

我的实体是:

@Entity
public class Author {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "author")
    private Set<AuthorBook> authorBooks;

    // getters and setters
}
@Entity
public class Book {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "book")
    private Set<AuthorBook> authorBooks;

    // getters and setters
}
@Entity
public class AuthorBook {

    @Id
    @GeneratedValue
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private Author author;

    @ManyToOne
    @JoinColumn(name = "book_id")
    private Book book;

    @Column(name = "isMainAuthor")
    private boolean isMainAuthor;
  
    // getters and setter
}

我的理解是我应该发出以下 POST 请求:

创建作者:

{
    "name": "Test Author"
}

创建一本书:

{
    "name": "Test Book"
}

创建映射:

{
    "author": {
        "id": 1
    },
    "book": {
        "id": 2
    },
    "isMainAuthor": true
}

首先:这是正确的使用方法吗?如果没有,我应该如何使用它?如果是,序列化应该如何工作?因为如果我这样做,然后获取书籍列表,响应将像这样无限长:

[
    {
        "id": 2,
        "name": "Test Book",
        "authorBooks": [
            {
                "id": 3,
                "author": {
                    "id": 1,
                    "name": "Test Author",
                    "authorBooks": [
                        {
                            "id": 3,
                            "author": {
                                "id": 1,
                                "name": "Test Author",
                                "authorBooks": [
                                    {
                                        "id": 3,
                                        "author": {
                                            "id": 1,
                                            "name": "Test Author",
                                            "authorBooks": [
    ...

我知道我可以在AuthorAuthorBookBook getter 上使用@JsonIgnore,在setter 上使用@JsonProperty,这样反序列化仍然有效。但是,作为一个对 Hibernate 没有经验的人,这对我来说似乎是一个 hack。解决这个问题的最干净和最好的方法是什么?

另外,有没有办法直接通过作者和书籍端点更新映射?我可能已经在数据库中有一个作者,并且想通过添加一个新的Book 实体并提供关系作为其中的一部分来添加他写的新书,但我似乎无法做到这一点。

【问题讨论】:

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


    【解决方案1】:

    这绝对不是黑客的把戏。使用@JsonIgnore 注解,这个问题就解决了。随着杰克逊 JSON 的发布,这个问题被称为无限递归,对此无能为力。为此,他们提出了一个注释。

    【讨论】:

    • 这绝对是一个限制,不是吗?也许我有充分的理由想在其他地方(即另一个端点)序列化 Entity?那我该怎么做呢?
    【解决方案2】:

    您可能需要在映射表中设置一个嵌入式 ID。保持AuthorBook 表不变,创建一个新类

    @Embeddable
    public class AuthorBookId{
    
      @Column(name = "user_id")
      private String authorId;
    
      @Column(name = "book_id")
      private String bookId;
    
    // Constructors
    // Getters and Setters
    }
    

    并将AuthorBook 表更改为

    @Entity
    public class AuthorBook {
    
      @EmbeddedId private AuthorBookId id = new AuthorBookId();
    
      @ManyToOne
      @MapsId("user_id")
      @JsonIgnore
      private Author author;
    
      @ManyToOne
      @MapsId("book_id")
      @JsonIgnore
      private Book book;
    
      @Column(name = "isMainAuthor")
      private boolean isMainAuthor;
    
      // getters and setter
    }
    

    【讨论】:

    • 你能解释一下它有什么作用以及它对我有什么作用吗?
    • 这将解决您的无限递归问题。此外,由于我们为映射实体手动创建单独的表,因此最好指定 ID,在本例中为嵌入式 ID。
    • 所以我认为你使用的@JsonIgnore 不起作用。相反,它需要在 getter 上,@JsonProperty 在 setter 上,否则我怎么能在我的请求中设置作者和书籍映射?但是,即使进行了更改并提出了与以前完全相同的请求,我还是得到了org.h2.jdbc.JdbcSQLIntegrityConstraintViolationException: NULL not allowed for column "USER_ID"; SQL statement: insert into author_book (is_main_author, user_id, book_id) values (?, ?, ?) [23502-200]
    • { "id": { "user_id": 1, "book_id": 1 }, "isMainAuthor": true } 你能像上面那样发送 JSON
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 2019-11-24
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 2017-01-03
    • 2017-01-12
    相关资源
    最近更新 更多