# 映射关系详解

表关系映射（双向映射）：

* @OneToOne 一对一关系
* @OneToMany 一对多
* @ManyToMany（不推荐使用，而是采用用中间对象，把多对多拆成两个对多一关系，如下书 与作者 的关系例子，还可以使用中间表用来搜索）

字段映射（单向映射）：

* @Embedded, @Embeddable 嵌入式关系（单向映射）
* @ElementCollection 集合一对多关系（单向映射）

> 注意：[hibernate jpa中 的 fetch](http://gong-10140.iteye.com/blog/678918)
>
> fetch 为关键映射的一个加载策略
>
> fetch的默认值：FetchType.EAGER，也就是加载的时候把响应的映射关系数据也加载出来
>
> 如果这不适合于应用程序或特定的持久字段，请将fetch设置为FetchType.LAZY，延迟加载，只要getxxxx（），具体获取时，再次执行一条sql语句获取

### @OneToOne 一对一关系

@OneToOne 属性

![](/files/-LfnTJndtk3185WXiky2)

比如作者和作者详情信息(一些不常用信息)，就是一个一对一

Author.java

```java
@Entity
public class Author {
    @OneToOne
    private AuthorInfo info;
    ...... 省略其他
}
```

AuthorInfo.java

```java
@Entity
public class AuthorInfo {

    private String school;

    @OneToOne(mappedBy = "info")
    private Author author;

    ......省略其他
}
```

无属性的一方拥有管理权，也就是author 表中会多出来一个字段info\_id

### @OneToMany 一对多， @ManyToOne 多对一

> 注意一对多关系映射时，“One”端采用@OneToMany 注释时必须使用mappedBy来指定Many端的对象的哪个属性提供了对应的关系映射。
>
> 避免建立单向关系映射，以免产生新的中间表，而采用双向映射关系（这样many 的一端只会使用外键方式来维护关系）

@ManyToOne 的属性

![](/files/-LfnTJnhesz-AYFkDRpv)

@OneToMany 属性

![](/files/-LfnTJnl_N_uFO_upJUr)

一本书有多个作者（OneToMany 一对多）， 而书和作者表中，（"spring boot", revin"）只能属于一本书（ManyToOne 多对一）

Book.java

```java
@Entity
public class Book {

    private String name;

    @OneToMany(mappedBy = "book")
    private List<BookAuthor> authors;

    .....省略
}
```

一个作者出版了多本书（OneToMany 一对多）， 而书和作者表中，（"spring boot", revin"）只能属于一个作者（ManyToOne 多对一）

Author.java

```java
@Entity
public class Author {
    @OneToMany(mappedBy = "author")
    //@OrderBy("book.name ASC")
    private List<BookAuthor> books;
     .....省略
}
```

BookAuthor .java

```java
@Entity
public class BookAuthor {

    @ManyToOne
    private Book book;

    @ManyToOne
    private Author author;
    .....省略
}
```

比如一本书可以分属于多个栏目（OneToMany 一对多），而同一个栏目 只能有一本相同的书（ManyToOne 多对一）

Book.java

```java
@Entity
public class Book {

    private String name;

    @ManyToOne
    private Category category;

    .....省略
}
```

Category.java

```java
public class Category {
@OneToMany(mappedBy = "category")
    private List<Book> books;

    ......省略其他
}
```

### @Embedded, @Embeddable 嵌入式关系

意思就是说当你有一个用户信息表中，这个人有地址信息，而地址信息有可能别的类有其他的关系映射，所以需要独立处理，但是address表中的字段，你有需要在用户表中存在这可以这种嵌入式关系。

@Embedded嵌入Address 类

```java
@Entity
public class Author {
    @Embedded
    private Address address;
    ......  省略其他
}
```

@Embeddable声明Address 类是可嵌入的

```java
@Embeddable
public class Address {

    private String province;

    private String city;

    private String area;

    private String address;

    private String zipcode;

    ...... 省略其他

}
```

最后生成出来 author表中会包含province，city，area，address，zipcode这些字段。

### @ElementCollection 集合一对多关系

```java
@Entity
public class Author {

    @id
    @GeneratedValue
    private long id

    @ElementCollection
    private List<String> hobbies;
    ......  省略其他
}
```

生成效果为：数据表会出现一张新表为`author_hobbies`,并且字段名为`author_id` 和 hobbies , Author表与hobbies表产生了一个一对 的关系。

当你插入和获取用户信息的时，jpa会自动关联。

再举例子

当一个用户有多个地址，比如在电子商务场景中，会有多个收货地址

```java
@Entity
public class Author {

    @ElementCollection
    private List<Address> addresses;
    ......  省略其他
}
```

也会重新生成一张新表，并且字段名是Address类定义的字段。Author与addresses产生一个一对的关系。

## 资料

[1JPA 批注参考](http://www.oracle.com/technetwork/cn/middleware/ias/toplink-jpa-annotations-100895-zhs.html#OneToMany) - 推荐当手册用


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://spring-boot.shujuwajue.com/guan-xi-xing-shu-ju-ku/spring-data-jpa/ying-she-guan-xi-xiang-jie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
