###### 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