###### tags: `JPA` # JPA 雙向關係 Bidirectional Relationships 雙向關係中一邊為owning side,另一邊為inverse side。 inverse side必須使用`@OneToOne`,`@OneToMany`或`@ManyToMany`的**mappedBy**屬性來指明owning side的參照外鍵的屬性名稱。 在一對多/多對一(One To Many / Many To One)的雙向關係中,多邊(many side)總是為owning side。多邊不應設定mappedBy。 在一對一(One To One)的雙向關係中,owning side為持有外鍵屬性的那一邊。 在多對多(Many To Many)的雙向關係中,因為多對多關係會有一個中介資料表,所以任一邊都可以是owning side(只能設定一邊為owning side)。 # One-to-One ### Library and Address ``` @Entity public class Library { @Id @GeneratedValue private long id; @Column private String name; @OneToOne @JoinColumn(name = "address_id") @RestResource(path = "libraryAddress", rel="address") private Address address; // standard constructor, getters, setters } ``` ``` @Entity public class Address { @Id @GeneratedValue private long id; @Column(nullable = false) private String location; @OneToOne(mappedBy = "address") private Library library; // standard constructor, getters, setters } ``` # Many-to-One / One-to-Many ### Library and Books ``` @Entity public class Book { @Id @GeneratedValue private long id; @Column(nullable=false) private String title; @ManyToOne @JoinColumn(name="library_id") private Library library; // standard constructor, getter, setter } ``` ``` public class Library { //... @OneToMany(mappedBy = "library") private List<Book> books; //... } ``` ### @JoinColumn and mappedBy #### Employee and Emails In a One-to-Many/Many-to-One relationship, the **owning side** is usually defined on the **'many'** side of the relationship. It's usually the side **which owns the foreign key**. #### @JoinColumn The **@JoinColumn** annotation defines that actual physical mapping on the **owning side**. ``` @Entity public class Email { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "employee_id") private Employee employee; // ... } ``` It simply means that our Email entity will have a foreign key column named employee_id referring to the primary attribute id of our Employee entity. #### mappedBy To make this association bidirectional, all we'll have to do is to define the **referencing side**. The inverse or the referencing side simply maps to the owning side. ``` @Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @OneToMany(fetch = FetchType.LAZY, mappedBy = "employee") private List<Email> emails; // ... } ``` Here, the value of mappedBy is the name of the association-mapping attribute on the owning side. With this, we have now established a bidirectional association between our Employee and Email entities. # Many-to-Many ### Authors and Books ``` @Entity public class Author { @Id @GeneratedValue private long id; @Column(nullable = false) private String name; @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "book_author", joinColumns = @JoinColumn(name = "book_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "author_id", referencedColumnName = "id")) private List<Book> books; //standard constructors, getters, setters } ``` ``` public class Book { //... @ManyToMany(mappedBy = "books") private List<Author> authors; //... } ``` ## 來源: https://matthung0807.blogspot.com/2019/05/hibernate-jpa-bidirectional.html https://codertw.com/%E8%B3%87%E6%96%99%E5%BA%AB/128556/ https://www.baeldung.com/jpa-many-to-many https://www.baeldung.com/spring-data-rest-relationships