## 1.核心概念
> Spring Data JPA是Spring数据家族的一部分,它使得基于JPA的存储库变得很容易。处理对基于JPA的数据访问层的增强支持。它使得构建使用数据访问技术的spring驱动的应用程序变得更加容易。
实现应用程序的数据访问层已经很麻烦了,为了执行简单的查询、分页和审计,必须编写太多的样板代码。Spring Data JPA的目标是通过减少工作来显著改进数据访问层的实现。
## 2.准备工作
- JDK 1.8或更高版本
- Gradle 4+或Maven 3.2+
- IntelliJ IDEA或其他开发工具
## 3.快速开始
### 新建项目

<br/>

<br/>

**pom.xml**
```
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springdatajpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springdatajpa</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
```
**application.yml**
```
server:
port: 8080
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: test
password: 123
h2:
console:
enabled: true
jpa:
open-in-view: true
hibernate:
ddl-auto: update
data:
jpa:
repositories:
bootstrap-mode: default
logging:
level:
org.hibernate.SQL: debug
```
**entity**
```
package com.example.springdatajpa.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/**
* <p>
* Customer
* </p>
*
* @author 秦煜彬
* @since 2020/8/29
*/
@ToString
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
```
说明:
@Entity: 指明了这是一个entity
@Table:指定生成的表名
@Id: 标记该entity的主键
@GeneratedValue: 提供主键的生成策略
**repository**
```
package com.example.springdatajpa.repository;
import com.example.springdatajpa.entity.Customer;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
/**
* <p>
* CustomerRepository
* </p>
*
* @author 秦煜彬
* @since 2020/8/29
*/
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
Customer findById(long id);
}
```
CustomerRepository扩展CrudRepository接口。与一起使用的实体和ID的类型,Customer以及Long在的通用参数中指定CrudRepository。通过扩展CrudRepository,CustomerRepository继承了一些用于Customer持久性的方法,包括保存,删除和查找Customer实体的方法。
Spring Data JPA还允许通过声明其他方法的方法签名来定义它们。例如,CustomerRepository包括findByLastName()方法。
在典型的Java应用程序中,可能希望编写一个实现的类CustomerRepository。但是,这就是Spring Data JPA如此强大的原因:无需编写存储库接口的实现。当运行应用程序时,Spring Data JPA将创建一个实现。
**controller**
```
package com.example.springdatajpa.controller;
import com.example.springdatajpa.entity.Customer;
import com.example.springdatajpa.repository.CustomerRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* Customer Controller
* </p>
*
* @author 秦煜彬
* @since 2020/8/29
*/
@Slf4j
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private CustomerRepository repository;
@GetMapping("/test")
public void test() {
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
log.info("Customers found with findAll():");
log.info("-------------------------------");
for (Customer customer : repository.findAll()) {
log.info(customer.toString());
}
log.info("");
Customer customer = repository.findById(1L);
log.info("Customer found with findById(1L):");
log.info("--------------------------------");
log.info(customer.toString());
log.info("");
log.info("Customer found with findByLastName('Bauer'):");
log.info("--------------------------------------------");
repository.findByLastName("Bauer").forEach(bauer -> {
log.info(bauer.toString());
});
log.info("");
}
}
```
**测试**
``curl http://127.0.0.1:8080/customer/test``
控制台:
```
2020-08-29 15:50:37.922 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : call next value for hibernate_sequence
2020-08-29 15:50:37.939 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : insert into customer (first_name, last_name, id) values (?, ?, ?)
2020-08-29 15:50:37.944 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : call next value for hibernate_sequence
2020-08-29 15:50:37.944 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : insert into customer (first_name, last_name, id) values (?, ?, ?)
2020-08-29 15:50:37.944 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : call next value for hibernate_sequence
2020-08-29 15:50:37.945 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : insert into customer (first_name, last_name, id) values (?, ?, ?)
2020-08-29 15:50:37.945 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : call next value for hibernate_sequence
2020-08-29 15:50:37.945 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : insert into customer (first_name, last_name, id) values (?, ?, ?)
2020-08-29 15:50:37.946 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : call next value for hibernate_sequence
2020-08-29 15:50:37.946 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : insert into customer (first_name, last_name, id) values (?, ?, ?)
2020-08-29 15:50:37.946 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customers found with findAll():
2020-08-29 15:50:37.946 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : -------------------------------
2020-08-29 15:50:38.009 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from customer customer0_
2020-08-29 15:50:38.014 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=1, firstName=Jack, lastName=Bauer)
2020-08-29 15:50:38.014 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=2, firstName=Chloe, lastName=O'Brian)
2020-08-29 15:50:38.014 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=3, firstName=Kim, lastName=Bauer)
2020-08-29 15:50:38.014 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=4, firstName=David, lastName=Palmer)
2020-08-29 15:50:38.014 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=5, firstName=Michelle, lastName=Dessler)
2020-08-29 15:50:38.014 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController :
2020-08-29 15:50:38.017 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer found with findById(1L):
2020-08-29 15:50:38.018 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : --------------------------------
2020-08-29 15:50:38.018 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=1, firstName=Jack, lastName=Bauer)
2020-08-29 15:50:38.018 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController :
2020-08-29 15:50:38.018 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer found with findByLastName('Bauer'):
2020-08-29 15:50:38.018 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : --------------------------------------------
2020-08-29 15:50:38.027 DEBUG 14424 --- [nio-8080-exec-2] org.hibernate.SQL : select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from customer customer0_ where customer0_.last_name=?
2020-08-29 15:50:38.029 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=1, firstName=Jack, lastName=Bauer)
2020-08-29 15:50:38.029 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController : Customer(id=3, firstName=Kim, lastName=Bauer)
2020-08-29 15:50:38.029 INFO 14424 --- [nio-8080-exec-2] c.e.s.controller.CustomerController :
```
到此,Spring Data JPA的快速开始就完成了。

Spring Data JPA(一) 快速开始