9. Data
SpringBoot集成了很多数据库技术,包含SQL和NoSQL。
9.1 SQL Databases
Spring框架对SQL提供广泛的支持,既可以使用JdbcClient或JdbcTemplate进行JDBC式的访问,也可以使用类似HIbernate这样的ORM框架。Spring Data提供了根据所定义的接口和其方法生成对应Repository实现的功能。
9.1.1 Configure a DataSource
Java的javax.sql.DataSource接口对数据库连接定义了一个标准的方法。通常,DataSource使用一个URL和对应认证信息来建立数据库连接。
Tip
在 the “How-to” section 中有一些高级的示例可以参考,来帮助你完全掌握DataSource的configuration。
Embedded Database Support
使用内嵌内存数据库来进行开发是非常方便的。当然这些内嵌内存数据库并不会对数据进行持久化。当应用关闭时,数据库的数据也会被丢弃。
Tip
"How-to"章节介绍了库如何初始化一个数据.
SpringBoot可以对内嵌的 H2, HSQL, 和Derby](db.apache.org/derby/)数据库进…
Note
如果在tests中使用到内嵌数据库,你会发现无论你使用多少个application context,都会使用同一个数据库。如果你想每一个context都会有自己独有的内嵌数据库,设置spring.datasource.generate-unique-name=true。
例如,一个典型的POM依赖如下所示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
Note
要想内嵌数据库被自动配置你还需要添加spring-jdbc的依赖。在上面pom示例中,它是通过spring-boot-starter-data-jpa传递依赖的。
Tip
如果你想为内嵌数据库配置一个连接URL,无论什么原因,请确保数据库的自动关闭是被禁用的。如果使用的是H2,配置DB_CLOSE_ON_EXIT=FALSE。如果使用的HSQLDB,确保没有配置shutdown=true。禁用数据库的自动关闭让SpringBoot可以SpringBoot控制数据库合适关闭,从而确保在数据库不再使用时进行关闭。
Connection to a Production Database
生产环境数据库的连接也可以使用池化的DataSource进行自动配置。
DataSource Configuration
配置项spring.datasource.*控制数据源的配置。比如,你需要在application.properties中声明一下内容
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
Note
至少应该配置spring.datasource.url来指定的URL,否则,SpringBoot会尝试对内嵌数据库进行自动化配置。
Tip
SpringBoot可以从URL推断出JDBC driver class。如果需要指定驱动类,请配置spring.datasource.driver-class-name。
Note
想要创建一个池化的DataSource,我们需要检查是否已提供了正确的驱动类。换句话说,如果你配置了spring.datasource.driver-class-name=com.mysql.jdbc.Driver,那么这个类就必须被加载。
在DataSourceProperties可以查阅更多配置项。这些配置项都是与具体数据库实现无关的。同样也可以通过使用数据库各自的前缀来调整具体数据库的参数 (spring.datasource.hikari.*, spring.datasource.tomcat.*, spring.datasource.dbcp2.*, and spring.datasource.oracleucp.*)。可以参阅你所使用的数据库连接池实现来获取更多信息。
例如,如果你使用Tomcat connection pool,你可以自定义很多额外的设置
spring.datasource.tomcat.max-wait=10000
spring.datasource.tomcat.max-active=50
spring.datasource.tomcat.test-on-borrow=true
该配置含义是如果等待10000ms获取不到数据库连接则抛出异常。将连接的最大数量限制为50并从连接池中使用连接前校验该连接。
Supported Connection Pools
SpringBoot使用下列算法来选择其实现
- HikariCP有着很好的性能和并发,因此,如果HikariCP 是可用的,我们选择它。
- 如果Tomcat pooling
DataSource是可用的,我们选择它。 - 如果 Commons DBCP2是可用的,我们选择它。
- 如果HikariCP, Tomcat, and DBCP2 都不可用,但Oracle UCP可用,我们选择它。
Note
如果你使用了 spring-boot-starter-jdbc或者spring-boot-starter-data-jpa "starters",那么会自动添加HikariCP依赖。
你也可以完全绕过选择算法,通过设置spring.datasource.type进行指定。这是非常重要的,因为如果你是在Tomcat容器中运行你的应用,tomcat-jdbc会被默认提供。
连接池随时都可以使用DataSourceBuilder进行手动配置。如果定义了你自己的DataSourcebean,自动配置便不会发生。下列的连接池是被DataSourceBuilder支持的。
- HikariCP
- Tomcat pooling
Datasource - Commons DBCP2
- Oracle UCP &
OracleDataSource - Spring Framework’s
SimpleDriverDataSource - H2
JdbcDataSource - PostgreSQL
PGSimpleDataSource - C3P0
9.1.2. Using JdbcTemplate
Spring的JdbcTemplate和NamedParameterJdbcTemplate类会被自动配置,所以你可以直接注入来使用他们。
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final JdbcTemplate jdbcTemplate;
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void doSomething() {
this.jdbcTemplate ...
}
}
你可以通过配置spring.jdbc.template.*来对template进行个性化
spring.jdbc.template.max-rows=500
Note
NamedParameterJdbcTemplate背后重用了同样的JdbcTemplate实例,如果定义了多个JdbcTemplate并且没有primary candidate,NamedParameterJdbcTemplate静不会自动配置。
9.1.3 Using JdbcClient
当NamedParameterJdbcTemplate存在时,Spring的JdbcClient会被自动配置,要使用时可以直接注入。
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
private final JdbcClient jdbcClient;
public MyBean(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public void doSomething() {
this.jdbcClient ...
}
}
9.1.4 JPA and Spring Data JPA
Java Presistence Api是一种可以让你将对象映射到相关数据库的标准技术。spring-boot-starter-data-jpa可以让你快速开始,其核心包含的依赖如下所示
- Hibernate 最流行的JPA实现
- Spring Data JPA 帮助你实现基于JPA的repositories。
- Spring ORM:spring框架的核心ORM支持
TIp
我们这里不会探讨太多关于JPA或者Spring Data 的太多细节。你可以在 “Accessing Data with JPA” 教程或者 Spring Data JPA and Hibernate 文档了解更多。
Entity Classes
通常JPA Entity在 persistence.xml文件中定义。但当使用SpringBoot时,该文件不再需要,而是使用SpringBoot的Entity Scanning。默认情况下, auto-configuration packages会被扫描。
被@Entity, @Embeddable, or @MappedSuperclass注解的会被扫描,下列是一个典型的entity。
import java.io.Serializable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@Entity
public class City implements Serializable {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String state;
// ... additional members, often include @OneToMany mappings
protected City() {
// no-args constructor required by JPA spec
// this one is protected since it should not be used directly
}
public City(String name, String state) {
this.name = name;
this.state = state;
}
public String getName() {
return this.name;
}
public String getState() {
return this.state;
}
// ... etc
}
Tip
你可以通过使用@EntityScan注解指定需要扫描entity的位置,具体请参阅“Separate @Entity Definitions from Spring Configuration”
Spring Data JPA Repositories
Spirng Data JPA repositories是一系列你所用来获取数据的接口。JPA的查询会根据你方法的名称自动创建。例如,在接口CityRepository中声明findAllByState(String state)方法来根据state查询所有的cities。
对于复杂查询,可以在方法上添加 Spring Data的Query注解。
Spring Data repositories通常继承自Repository 或CrudRepository接口。如果你使用自动配置,那么会扫描auto-configuration packages 下的repositoriees。
Tip
可以通过@EnableJpaRepositories注解来指定扫描respositories的位置。
下面示例展示了一个典型的Spring Data repository接口是怎么定义的
import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.City;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}
Spring Data JPA repositories支持三种不同的引导方式:default,deferred和lazy。要想启用deferred 或lazy 引导,设置spring.data.jpa.repositories.bootstrap-mode配置项。当使用deferred 或者lazy引导时,会使用context的AsyncTaskExecutor,如果多个bootstrap executor存在时,则使用名为applicationTaskExecutor的那个。
Tip
关于Spring Data JPA的细节,请查阅Spring Data JPA reference documentation.
Creating and Dropping JPA Databases
默认情况下,只有你在使用内嵌数据库(H2,HSQL,或 Derby)的时候JPA数据库才会自动创建。你可以使用spring.jpa.*配置项对其进行配置。例如,通过添加下面配置来创建和删除表。
spring.jpa.hibernate.ddl-auto=create-drop
Note
Hibernate有响应的自己的配置项:hibernate.hbm2ddl.auto。你也可以使用它,通过spring.jpa.properties.*来对Hibernate原生的配置项进行设置。
spring.jpa.properties.hibernate[globally_quoted_identifiers]=true
该配置将把Hibernate的entity manager的hibernate.globally_quoted_identifiers属性设置为true。
默认情况下,会在ApplicationContext已经启动后才执行DDL。
9.1.5 Spring Data JDBC
Spring Data为JDBC提供了respository的支持,并且会为CrudRepository里的方法自动生成SQL。@Query用于复杂查询。
只需要添加 spring-boot-starter-data-jdbc依赖,SpringBoot会为Spring Data JDBC进行自动配置。添加 @EnableJdbcRepositories 注解或者实现AbstractJdbcConfiguration都可以对Spring Data JDBC进行自定义配置。
关于Spring Data JDBC细节,参阅reference documentation.
9.1.6 Using H2's Web Console
H2数据库提供了一个浏览器端的console,当下列条件满足时,该console会被自动配置。
- 当前应用为基于servlet的web应用
com.h2database:h2在classpath中- 正在使用SpringBoot developer tools
Tip
如果你没有使用developer tools但还想使用H2的console,那么仅需要配置spring.h2.console.enabled为true。
Changing the H2 Console‘s Path
默认情况下,console的path为/h2-console,你可以通过spring.h2.console.path配置项进行修改。