JPA与特定级联类型的多对多关系

时间:2018-08-13 06:52:23

标签: hibernate spring-data-jpa spring-data many-to-many hibernate-mapping

对于我的任务,我需要使用JPA创建多对多关系,但必须使用额外的列手动指定联结表。 数据结构如下:

  • 书籍(id,名称,出版,体裁,等级)
  • 作者(身份证,姓名,性别,出生地)
  • 图书作者(ID,图书ID,作者ID)

我创建了这样的实体:

作者:

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "authors")
public class Author {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @Column(name = "name", length = 60)
  private String name;

  @Enumerated(EnumType.STRING)
  private Gender gender;

  private Date born;

  @OneToMany(mappedBy = "author",cascade = CascadeType.ALL, orphanRemoval = 
     true, fetch = FetchType.EAGER)
  private Set<AuthorBook> authorBooks = new HashSet<>();

}

图书:

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "books")
public class Book {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  private String name;

  private Date published;

  private String genre;

  private BigDecimal rating;

  @OneToMany(mappedBy = "book",cascade = CascadeType.REMOVE, fetch = 
    FetchType.EAGER)
  @OnDelete(action = OnDeleteAction.CASCADE)
  private Set<AuthorBook> authorBooks = new HashSet<>();

}

AuthorBook:

@Data
@EqualsAndHashCode(exclude = {"book", "author"})
@Entity
@Table(name = "author_book")
public class AuthorBook implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

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

  @ManyToOne(cascade = CascadeType.ALL)
  @JoinColumn(name = "author_id")
  private Author author;
}

我插入到表中的数据集:

Books表:

 id       name              published       genre               rating
 1     'Залишенець'         '2005-02-03'    'historical novel'  '5'
 2     'Ключ'               '1999-01-01'    'novel'             '3'
 3     'Effective Java'     '2001-03-02'    'technical'         '5'
 4     'Java Concurrency'   '2006-04-23'    'technical'         '4'
 5     'Java Puzzlers'      '2005-02-02'    'technical'         '4'
 6     'Patterns'           '2002-06-25'    'technical'         '3'
 7     'Harry Potter'       '1997-06-26'    'fantasy'           '5'
 8     'The Programmer'     '1999-09-21'    'education'         '5'
 9     'The Lost Symbol'     null           'crime'             '4'

作者表:

id            name                  gender       born    
1      'Шкляр Василь Миколайович'   'male'      '1951-06-10'
2      'Joshua Bloch'               'male'      '1961-07-28'
3      'Martin Fowler'              'male'       null
4      'Chad Fowler'                'male'       null
5      'J. K. Rowling'              'female'    '1965-07-31'
6      'Dan Brown'                  'male'      '1964-06-22'
7      'Suzanne Collins'            'female'    '1962-08-10'

AuthorBook表:

id   book_id   author_id
 1    1       1
 2    2       1
 3    3       2
 4    4       2
 5    5       2
 6    6       3
 7    9       6
 8    8       4
 9    7       5

例如,当我删除id = 2的书时,它将删除id = 1的作者。有什么办法可以删除书而不删除绑定作者。与作者表相同:删除作者时,我不应该删除他的书。我是Spring Data JPA的新手,对不起,如果这个问题很愚蠢。

更新

我从AuthorBook实体的@ManyToOne批注中删除了层叠类型,现在看起来像这样:

public class AuthorBook implements Serializable {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

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

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

Book和Author实体保持不变。 现在,当我尝试使用JPA的deleteById(idValue)删除ID = 1的书时,它会抛出

javax.persistence.EntityNotFoundException: Unable to find Book with id 1

它实际上是从books表中删除书,但没有从AuthorBook表中删除关联的记录,我的意思是没有id = 1的书留在books表中,但是在AuthorBook表中仍然有记录:

id   book_id   author_id
1     1         1 

删除ID = 1的图书记录后的MySql屏幕截图

AuthorBook表 enter image description here

书桌: enter image description here

作者表:enter image description here

1 个答案:

答案 0 :(得分:0)

您正在强制实体使用此标签删除从属记录  (cascade = CascadeType.ALL)

CascadeType.ALL的含义是,持久性会将所有EntityManager操作(PERSIST,REMOVE,REFRESH,MERGE,DETACH)传播(层叠)到相关实体。

如果您不想删除从属记录,请从实体中删除此标记,这可能会导致在表中留下孤立记录(不是一个好习惯)。