Spring Boot SQL Databases(Spring Boot 3.1.5 Reference 翻译)

104 阅读7分钟

9. Data

SpringBoot集成了很多数据库技术,包含SQL和NoSQL。

9.1 SQL Databases

Spring框架对SQL提供广泛的支持,既可以使用JdbcClientJdbcTemplate进行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的JdbcTemplateNamedParameterJdbcTemplate类会被自动配置,所以你可以直接注入来使用他们。

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通常继承自RepositoryCrudRepository接口。如果你使用自动配置,那么会扫描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配置项进行修改。