# 配置与注解备注

## 配置备注

### `spring.jpa.generate-ddl` 与 `spring.jpa.hibernate.ddl-auto`

spring.jpa.hibernate.ddl-auto 其实对应的是hibernate里的`hibernate.hbm2ddl.auto.`

默认情况下，DDL执行（或验证）被延迟到ApplicationContext启动。这也有一个spring.jpa.generate-ddl标识，如果Hibernate自动配置被激活，那该标识就不会被使用，因为ddl-auto设置粒度更细，推荐。

`spring.jpa.hibernate.ddl-auto 支持的值：`

* ddl-auto:create----每次运行该程序，没有表格会新建表格，表内有数据会清空
* ddl-auto:create-drop----每次程序结束的时候会清空表
* ddl-auto:update----每次运行程序，没有表格会新建表格，表内有数据不会清空，只会更新
* ddl-auto:validate----运行程序会校验数据与数据库的字段类型是否相同，不同会报错

`spring.jpa.generate-ddl支持 值:`

* true
* false

## 注解备注

### `@EntityGraph注解`

[JPA效率优化（EntityGraph）](https://blog.csdn.net/dalangzhonghangxing/article/details/56680629)

例子： 表示根据name查询书的时候也把关联 category的信息和作者信息都查出来

```java
public interface BookRepository extends BookShopRepository<Book> {

    @EntityGraph(attributePaths = { "category","authors"  })
    Book findByName(String bookname);

}
```

可以统一写在对象实体类上面，并且以一个自定义的name命名，这样中就可以使用名字来统一引用

entity实体类中：

```java
@Entity
@NamedEntityGraph(name = "Book.fetch.category.and.author", attributeNodes = {
 @NamedAttributeNode("category"),
 @NamedAttributeNode("authors")
})
public class Book extends DomainImpl {
  ....省略
}
```

BookRepository 类中就可以使用名字进行引用

```java
public interface BookRepository extends BookShopRepository<Book> {

    @EntityGraph("Book.fetch.category.and.author")
    Book findByName(String bookname);

}
```

这样做的好处是如果抓取策略变了，只需要改源头，因为引用处都是使用name

### `@Inheritance注解`

实体继承策略的注解

JPA提供了三种继承映射策略：

* 1、 一个类继承结构一个表的策略。这是继承映射的默认策略。即如果实体类B继承实体类A，实体类C也继承自实体A，那么只会映射成一个表，这个表中包括了实体类A、B、C中所有的字段，JPA使用一个叫做“discriminator列”来区分某一行数据是应该映射成哪个实体。注解为：`@Inheritance(strategy = InheritanceType.SINGLE_TABLE)`
* 2、 联合子类策略。这种情况下子类的字段被映射到各自的表中，这些字段包括父类中的字段，并执行一个join操作来实例化子类。注解为：`@Inheritance(strategy = InheritanceType.JOINED)`
* 3、 每个具体的类一个表的策略。注解为：`@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)`

```java
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Book {
}
```

> 注意：如果使用`TABLE_PER_CLASS`这种策略主键是不能使用自增主键策略，因为`TABLE_PER_CLASS`会每个具体类创建一个表，每个表都有自己的主键，如果使用自增策略，这两个表里的主键有可能会重复，导致语句查询时候产生混乱。则需要自己写主键id的生成策略
>
> ```java
> @Id
> @GeneratedValue(generator = "sequenceGenerator")
> @GenericGenerator(name = "sequenceGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
>     parameters = {
>         @Parameter(name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "ID_SEQUENCE"),
>         @Parameter(name = SequenceStyleGenerator.INITIAL_PARAM, value = "1000"),
>         @Parameter(name = SequenceStyleGenerator.INCREMENT_PARAM, value = "1"),
>         @Parameter(name = SequenceStyleGenerator.OPT_PARAM, value = "pooled"),
>     }
> )
> private Long id;
> ```

[JPA实体继承实体的映射策略](https://blog.csdn.net/mhmyqn/article/details/37996673)

[hibernate 在mysql数据库上，利用sequence生成主键的另一种解决方法](http://bastengao.iteye.com/blog/1105650)

### `@Basic注解`

JPA不会去修改已经生成出来的表名或者字段名，新增的字段，如果没有添加任何注释标签，则自动会有一个`@Basic`注解，作用就是自动会在数据库中添加此字段。

### `@Table注解`

当你的entity名和你表名不一致时，`@Table(name="CUSTOMERS") ，@Tablel来明确指定一个表名。`

### `@Column注解`

当你的entity属性名和数据库中的字段名不一致，可以使用`@Column` 明确指定，它也可以设置一些属性

```java
@Column(length = 10, nullable = false, unique = true)
```

```java
@Column(columnDefinition = "INT(3)")
private int age;
```

支持的参数，参考：[@Column 注解详情](https://www.cnblogs.com/ConfidentLiu/p/7710493.html) , [JPA的Column注解总结](https://www.cnblogs.com/quickcodes/p/JPA-deColumn-zhu-jie-zong-jie.html)

* unique属性表示该字段是否为唯一标识，默认为false。如果表中有一个字段需要唯一标识，则既可以使用该标记，也可以使用@Table标记中的@UniqueConstraint。
* nullable属性表示该字段是否可以为null值，默认为true。
* insertable属性表示在使用“INSERT”脚本插入数据时，是否需要插入该字段的值。
* updatable属性表示在使用“UPDATE”脚本插入数据时，是否需要更新该字段的值。insertable和updatable属性一般多用于只读的属性，例如主键和外键等。这些字段的值通常是自动生成的。
* columnDefinition属性表示创建表时，该字段创建的SQL语句，一般用于通过Entity生成表定义时使用。
* table属性表示当映射多个表时，指定表的表中的字段。默认值为主表的表名。有关多个表的映射将在本章的5.6小节中详细讲述。
* length属性表示字段的长度，当字段的类型为varchar时，该属性才有效，默认为255个字符。
* precision属性和scale属性表示精度，当字段类型为double时，precision表示数值的总长度，scale表示小数点所占的位数。

### `@Transient注解`

@Transient表示该属性并非一个到数据库表的字段的映射,ORM框架将忽略该属性.

如果一个属性并非数据库表的字段映射,就务必将其标示为`@Transient`,否则,ORM框架默认其注解为`@Basic`

示例:

```java
//根据birth计算出age属性 
@Transient 
public int getAge() { 
    return getYear(new Date()) - getYear(birth); 
}
```

### @Enumerated`注解`

```
@Enumerated(EnumType.STRING)
private Gender gender;
```

Gender.java

```java
public enum Gender {
    male("男"),
    female("女");

    private String name;
    }

    public String getName(){
        return this.name;
    }
}
```

这样存入数据库中时是枚举字符串，而非0 ，1 的数字

[JPA关于枚举类型的处理](https://www.jianshu.com/p/71185c21f5b5)

[JPA 中@Enumerated](https://blog.csdn.net/qq_38157516/article/details/80540505)

[JPA之日期和枚举的JPA映射](https://blog.csdn.net/BruceLeeNumberOne/article/details/77828603)

### @Temporal`注解`

```
@Temporal(TemporalType.DATE)
private Date birthday;
```

为日期格式：2018-06-18

```java
@Temporal(TemporalType.TIME)
```

为时间格式：22:50:30

```java
@Temporal(TemporalType.TIMESTAMP)
```

日期和时间(默认)格式:2011-06-18 22:51:34.0

[Hibernate JPA注解 @Temporal(TemporalType.DATE) 日期注解!](https://blog.csdn.net/u013456370/article/details/52691093)

### `@Valid`

字段验证

[使用validator-api来验证spring-boot的参数](https://www.cnblogs.com/mawang/p/6767906.html)

### @MappedSuperclass

当有entity里有共同的属性字段，比如说id，则可以把他提炼出来一个父类，并且加上`@MappedSuperclass`，则实体基类就可以继承了

### `@NoRepositoryBean`

启动时不初始化该实体类。是spring date jpa的一种注解

[Spring Data JPA: 为所有Repository添加自定义方法](https://www.tianmaying.com/tutorial/spring-jpa-custom-all)


---

# 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/bei-zhu.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.
