1. 前言
本节讲解如何使用spring-data-jpa来访问数据,通过内存数据库h2来存储数据。在这个过程中,我们将了解到:
spring-data-jpa
的特点和强大之处- 如何使用内存数据库
h2
2. 环境要求
使用环境参考Spring Boot基础教程汇总中的讲解:详情请点击
3. 快速开始
使用maven构建项目
- 项目结构如下:
└─src
├─main
│ ├─java
│ │ └─com
│ │ └─qingtian
│ │ ├─entity
│ │ └─service
│ └─resources
└─test
└─java
└─com
└─qingtian
- pom.xml,特别注意,其中
spring-boot-starter-data-jpa
和h2
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qingtian</groupId>
<artifactId>spring-boot-jpa-h2</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<name>spring-boot-jpa-h2</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
代码详解
设计
User
类,并使用注解@Entity
将其标识为JPA的实体src/main/java/com/qingtian/entity/User.java
@Entity
public class User {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
protected User() {}
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"User[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
// 省略了getter和setter
}
在User
中定义了id
,firstName
,lastName
这三个属性,同时定义了两个构造器,其中定义无参构造器是因为JPA需要,我们不会用到它,所以定义为protected
,另一个构造器用来初始化实例。
使用@Entity
表示为JPA实体,不使用@Table
注解,则默认使用User
类名作为表名。
使用@Id
表示字段id为表的主键,@GeneratedValue(strategy= GenerationType.AUTO)
表明主键自增长。
设计
UserRepository
接口操作User
对象src/main/java/com/qingtian/service/UserRepository.java
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByLastName(String lastName);
}
UserRepository
继承CrudRepository<T,ID>
,其中T表示entity,ID表示为table的主键。CrudRepository
中封装好了一些方法,包括对User
的查找,删除,更新等,这是Spring Data JPA特点之一。
当然,Spring Data JPA也允许在UserRepository
操作类中定义其他的方法,比如我们在这里定义了findByLastName
。从字面上的意思便是通过lastName
字段来查询User。
一旦UserRepository
继承了CrudRepository
,我们便无须为UserRepository
接口创建实现类,在运行application时,Spring Data JPA会为我们动态创建一个实现类,这就是其强大的地方之一。并且,在执行findByLastName
方法时,会根据方法名和参数来执行方法,并不需要我们去实现和写sql
设计
Demo
来执行UserRepository
的curd操作。src/main/java/com/qingtian/Demo
@Component
public class Demo implements CommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(Demo.class);
@Autowired
private UserRepository repository;
@Override
public void run(String... args) throws Exception {
// 插入5个用户
repository.save(new User("Jack", "Bauer"));
repository.save(new User("Chloe", "O'Brian"));
repository.save(new User("Kim", "Bauer"));
repository.save(new User("David", "Palmer"));
repository.save(new User("Michelle", "Dessler"));
// 查询用户列表
log.info("Customers found with findAll():");
log.info("-------------------------------");
for (User user : repository.findAll()) {
log.info(user.toString());
}
log.info("");
// 通过id查询某个用户
repository.findById(1L)
.ifPresent(user -> {
log.info("Customer found with findById(1L):");
log.info("--------------------------------");
log.info(user.toString());
log.info("");
});
// 通过lastName查询用户
log.info("Customer found with findByLastName('Bauer'):");
log.info("--------------------------------------------");
repository.findByLastName("Bauer").forEach(bauer -> {
log.info(bauer.toString());
});
log.info("");
}
}
在这里使用CommandLineRunner
的实现类来执行curd操作。如果需要在SpringApplication
启动后执行一些特殊的代码,便可以实现CommandLineRunner
,并使用@Component
将实现类注入到容器中。
CommandLineRunner
接口提供单一的run
方法,该方法会在SpringApplication.run(...)
完成之前调用。
设计
application
src/main/java/com/qingtian/SpringBootJpaH2Application
@SpringBootApplication
public class SpringBootJpaH2Application {
public static void main(String[] args) {
SpringApplication.run(SpringBootJpaH2Application.class, args);
}
}
不了解@SpringBootApplication
注解的,可以参考下构建spring-rest-curd + 单元测试
- 运行查看结果
在程序的根目录下(与pom.xml同级),执行
mvn spring-boot:run
4. 总结
Spring Data JPA有以下特点:
1. CrudRepository
实现了一些简单的增删查改等方法,继承该类便可以使用,不用用户重复开发
2. demoRepository
接口继承CrudRepository
,不用编写实现类,会在项目运行时动态创建
3. 会根据方法名和参数自动实现一些简单的查询,比如本文的findByLastName
h2(内存数据库):
1. 使用起来非常方便,不需要提供任何连接URLs
,只需要添加想使用的的内嵌数据库依赖。
2. 只需要在应用启动时填充数据库,在应用结束前清楚数据
5. 附录
项目源码,欢迎star,本小节为spring-boot-jpa-h2:https://github.com/mcrwayfun/spring-boot-learning