# Spring Data JPA 使用方法

***

JPA是Java官方定义的一套与数据库交互的接口标准。Spring Data JPA 实现了它，并且整合了多种数据库，使得与数据库的交互变得简单。

使用Spring Data JPA的逻辑：

> 在springApplication设置里设置数据源（datasource）；
>
> 编写一个实体类，其中的属性对应数据库表单的列；
>
> 为这个实体类添加注解，使其能够与数据表衔接；
>
> 定义Dao（Repository），使用它来与数据库进行交互。

## 一、导入包

首先用maven导入包：

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
  	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
 </dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
```

这里导入lombok，用于生成构造方法；导入mysql-connector，用于连接mysql数据库，与mysql交互这个是必须的。

## 二、创建数据库

在外部（cmd）登录mysql并使用SQL语句创建数据库`jpatest`，新建一个表`users`用来储存用户数据。

```sql
mysql> create table users (
    -> id int,
    -> name char(30),
    -> password char(30),
    -> userInfoId int);
```

然后用ALTER指令设置id为主键，并设置其为自增。

创建完成后可以用IDEA自带的database工具登录数据库并查看：

![IDEA的database工具](https://s1.328888.xyz/2022/09/17/o9Gan.png)

> 这里注意，IDEA的database窗口只是用于预览数据库和数据表，并不能让项目连上数据库。还需要手动设置datasource。

## 三、配置数据源

在Spring设置（`application.properties`，一般在`resources`目录下，也有一种写为yml形式）中添加如下语句以添加数据源：

```properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jpatest?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=password
```

这样就指定了一个数据源，其驱动为mysql驱动，数据库的url为`mysql://localhost:3306/jpatest`，也就是`jpatest`数据库。然后我们指定了用户名和密码。

## 四、创建实体类

对应我们的需求和数据库的各列，我们新建下面的User类：

```java
import lombok.*;
import javax.persistence.*;

@Data
@RequiredArgsConstructor
@NoArgsConstructor
@Entity
@Table(name="users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @NonNull
    private String name;
    @NonNull
    private String password;
    @NonNull
    @Column(name="userinfoid")
    private int userInfoId;
}
```

下面对类上的注解进行说明。这些注解都是由`javax.persistence`定义的。

### @Data、@RequiredArgsConstructor 和@NoArgsConstructor

都是lambok提供的。`@Data`提供getter和setter，`@NoArgsConstructor`提供`@Entity`要求的无参构造方法，而`@RequiredArgsConstructor`则提供仅包含必须的几个属性（这里是除了id以外的属性，因为id我们希望它自动生成）的构造方法。

`@RequiredArgsConstructor` 只会识别带有lombok的`@NonNull`注解或`final`修饰符的属性。所以在相关属性上加上`@NonNull`。

> p.s. 好像很多人用`@RequiredArgsConstructor`不需要使用@NonNull，但我本地没办法不用@NonNull实现。

### @Entity、@Id 和 @Table

`@Entity`注解会将这个类表示为准备映射数据库的实体类，必须结合@Id注解使用。

`@Id`所标注的属性会被识别为主键。一个表必须有主键，所以必须存在这个注解。

> `@GeneratedValue`用于给主键指定生成策略，一般用`GenerationType.IDENTITY`来指定主键为自增。这里的注解设置必须和数据库一致，否则会出错。

`@Table`用于标识需要对应的数据表名。如`@Table(name="users")`表示对应的是数据源下的`users`这个表。

### @Column

这个注解用于属性上，可写可不写，用于指定这个属性所对应的列的名字。如果不写，那么指定的列默认是和这个属性名字相同的列。注意大小写是敏感的，要和数据库严格一致。

## 五、创建UserRespository

这就是所谓的Dao层，由Spring提供具体实现。我们在这里需要定义一个接口`UserRespository`，继承Spring提供的接口`JpaRepository< >`以使用Spring提供的方法。

```java
@Repository
public interface UserRepository extends JpaRepository<User,Integer> {

}
```

### 说明：

* `JpaRepository< >`需要提供实体类和ID（主键）的类；
* 为了之后让Spring托管这个类，加上`@Repository`注解使之被定义为一个bean；
* 只要留空这个接口就可以使用了。

在留空这个接口的情况下，就可以执行`save`，`saveall`，`delete`，`find`等等的CRUD（增删查改）操作了。但是由于`JpaRepository`实现的时候不知道你的类有哪些属性，所以要进行一些具体的操作，比如`findByPassword`（根据密码查找用户），就必须要在这个接口下自定义一些方法来完成。

Spring Data的一个强大的功能在于，你只需要在接口定义这个方法，而不需要实际写代码来实现它，Spring框架会自动理解你的方法的目的，并自动帮你实现想要的操作。

例如，上面提到的`findByPassword`可以直接用这样的方式实现：

UserRepository：

```java
@Repository
public interface UserRepository extends JpaRepository<User,Integer> {
    public User getByPassword(String passwd);
}
```

test()：

```java
user = userRepository.getByPassword("123");
```

虽然我们没有编写任何实现相关代码，但Spring仍通过解析方法名的意义帮你完成了你想要的操作。

除了匹配具体的数值，方法名的解析还支持值区间、包含、前缀等等非常丰富的匹配方法。这些方法在书写时IDEA都会提供补全的提示，非常方便。

当然，有时候我们还是会想用sql的方式进行操作，也可以使用`@Query`注解实现。

例子：

```java
    @Query(value = "select u from User u where u.password='123'")
    public User getByPassword2();
```

这个语法和原生的sql有所不同，需要单独查阅。
