Spring框架提供了利用使用SQL数据库,直接JDBC访问广泛的支持JdbcTemplate来完成“对象关系映射”技术,比如Hibernate。 Spring Data提供了更高级别的功能:Repository直接从接口创建实现,并使用约定从您的方法名称生成查询。

11.1 配置数据源

Java的javax.sql.DataSource界面提供了使用数据库连接的标准方法。传统上,“数据源”使用URL以及一些凭据来建立数据库连接。

有关更多高级示例,请参见“操作方法”部分,通常可以完全控制DataSource的配置。

11.1.1 嵌入式数据库支持

使用内存嵌入式数据库来开发应用程序通常很方便。显然,内存数据库不提供持久存储。您需要在应用程序启动时填充数据库,并准备在应用程序结束时丢弃数据。

“操作方法”部分包括有关如何初始化数据库的部分

Spring Boot可以自动配置嵌入式H2HSQLDerby数据库。您无需提供任何连接URL。您只需要包含要使用的嵌入式数据库的构建依赖项即可。

如果在测试中使用此功能,则可能会注意到,整个测试套件将重用同一数据库,而不管您使用的应用程序上下文的数量如何。如果要确保每个上下文都有一个单独的嵌入式数据库,则应设置spring.datasource.generate-unique-nametrue

例如,典型的POM依赖关系如下:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-jpa</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.hsqldb</groupId>
  7. <artifactId>hsqldb</artifactId>
  8. <scope>runtime</scope>
  9. </dependency>
您需要依赖项spring-jdbc才能自动配置嵌入式数据库。在此示例中,它通过传递spring-boot-starter-data-jpa
如果出于某种原因确实为嵌入式数据库配置了连接URL,请确保确保禁用了数据库的自动关闭功能。如果使用H2,则应使用H2 DB_CLOSE_ON_EXIT=FALSE。如果使用HSQLDB,则应确保shutdown=true未使用它。通过禁用数据库的自动关闭功能,Spring Boot可以控制何时关闭数据库,从而确保一旦不再需要访问数据库时就可以执行该操作。

11.1.2 连接到生产数据库

生产数据库连接也可以使用pooling进行自动配置DataSource。Spring Boot使用以下算法来选择特定的实现:

  1. 我们更喜欢HikariCP的性能和并发性。如果HikariCP可用,我们总是选择它。
  2. 否则,如果Tomcat池DataSource可用,我们将使用它。
  3. 否则,如果Commons DBCP2可用,我们将使用它。
  4. 如果没有HikariCP,Tomcat和DBCP2,并且如果有Oracle UCP,我们将使用它。

如果使用spring-boot-starter-jdbcspring-boot-starter-data-jpa“启动器”,则会自动获得对的依赖HikariCP

您可以完全绕过该算法,并通过设置spring.datasource.type属性来指定要使用的连接池。如果您在tomcat-jdbc默认情况下提供的Tomcat容器中运行应用程序,则这一点尤其重要。
其他连接池始终可以手动配置。如果定义自己的DataSourcebean,则不会进行自动配置。

DataSource配置由中的外部配置属性控制spring.datasource.*。例如,您可以在中声明以下部分application.properties
物产
Yaml

  1. spring.datasource.url=jdbc:mysql://localhost/test
  2. spring.datasource.username=dbuser
  3. spring.datasource.password=dbpass
您至少应通过设置spring.datasource.url属性来指定URL 。否则,Spring Boot会尝试自动配置嵌入式数据库。
Spring Boot可以从URL推断大多数数据库的JDBC驱动程序类。如果需要指定特定的类,则可以使用该spring.datasource.driver-class-name属性。
对于DataSource要创建的池,我们需要能够验证有效的Driver类是否可用,因此我们在进行任何操作之前都要进行检查。换句话说,如果您设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,则该类必须是可加载的。

请参阅DataSourceProperties以获取更多受支持的选项。这些是不管实际实现如何都起作用的标准选项。它也有可能微调实现特定的设置,使用各自的前缀(spring.datasource.hikari.*spring.datasource.tomcat.*spring.datasource.dbcp2.*spring.datasource.oracleucp.*)。有关更多详细信息,请参阅所用连接池实现的文档。
例如,如果使用Tomcat连接池,则可以自定义许多其他设置,如以下示例所示:
物产
Yaml

  1. spring.datasource.tomcat.max-wait=10000
  2. spring.datasource.tomcat.max-active=50
  3. spring.datasource.tomcat.test-on-borrow=true

如果没有可用连接,这会将池设置为在引发异常之前等待10000 ms,将最大连接数限制为50,并在从池借用连接之前验证连接。

11.1.3 连接到JNDI数据源

如果您将Spring Boot应用程序部署到Application Server,则可能需要使用Application Server的内置功能来配置和管理DataSource,并使用JNDI对其进行访问。
spring.datasource.jndi-name属性可以被用作一个替代spring.datasource.urlspring.datasource.usernamespring.datasource.password属性来访问DataSource从一个特定的JNDI位置。例如,以下部分application.properties显示了如何访问定义的JBoss AS DataSource
物产
Yaml

  1. spring.datasource.jndi-name=java:jboss/datasources/customers

11.2 使用JdbcTemplate

SpringJdbcTemplateNamedParameterJdbcTemplateclass是自动配置的,您可以将@Autowire它们直接放入自己的bean中,如以下示例所示:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.jdbc.core.JdbcTemplate;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class MyBean {
  6. private final JdbcTemplate jdbcTemplate;
  7. @Autowired
  8. public MyBean(JdbcTemplate jdbcTemplate) {
  9. this.jdbcTemplate = jdbcTemplate;
  10. }
  11. // ...
  12. }

您可以使用属性来自定义模板的某些属性spring.jdbc.template.*,如以下示例所示:
物产
Yaml

  1. spring.jdbc.template.max-rows=500
NamedParameterJdbcTemplate重复使用相同的JdbcTemplate幕后情况。如果JdbcTemplate定义了多个,并且不存在主要候选对象,NamedParameterJdbcTemplate则不会自动配置。

11.3 JPA和Spring Data JPA

Java Persistence API是一种标准技术,可让您将对象“映射”到关系数据库。该spring-boot-starter-data-jpaPOM提供了上手的快捷方式。它提供以下关键依赖性:

11.3.1 实体类别

传统上,JPA“实体”类在persistence.xml文件中指定。在Spring Boot中,此文件不是必需的,而是使用“实体扫描”。默认情况下,将搜索主配置类(用@EnableAutoConfiguration或注释的一个@SpringBootApplication)下的所有软件包。
任何类别标注了@Entity@Embeddable或者@MappedSuperclass被认为是。典型的实体类类似于以下示例:

  1. package com.example.myapp.domain;
  2. import java.io.Serializable;
  3. import javax.persistence.*;
  4. @Entity
  5. public class City implements Serializable {
  6. @Id
  7. @GeneratedValue
  8. private Long id;
  9. @Column(nullable = false)
  10. private String name;
  11. @Column(nullable = false)
  12. private String state;
  13. // ... additional members, often include @OneToMany mappings
  14. protected City() {
  15. // no-args constructor required by JPA spec
  16. // this one is protected since it shouldn't be used directly
  17. }
  18. public City(String name, String state) {
  19. this.name = name;
  20. this.state = state;
  21. }
  22. public String getName() {
  23. return this.name;
  24. }
  25. public String getState() {
  26. return this.state;
  27. }
  28. // ... etc
  29. }
您可以使用@EntityScan注释来自定义实体扫描位置。请参阅“ howto.html ”方法。

11.3.2 Spring Data JPA存储库

Spring Data JPA存储库是可以定义以访问数据的接口。JPA查询是根据您的方法名称自动创建的。例如,一个CityRepository接口可能声明了findAllByState(String state)一种查找给定州所有城市的方法。
对于更复杂的查询,您可以使用Spring Data的Query注释对方法进行注释。
Spring Data存储库通常从RepositoryCrudRepository接口扩展。如果您使用自动配置,则会从包含主配置类(用@EnableAutoConfiguration或注释的主配置类)的软件包中搜索存储库@SpringBootApplication
以下示例显示了典型的Spring Data存储库接口定义:

  1. package com.example.myapp.domain;
  2. import org.springframework.data.domain.*;
  3. import org.springframework.data.repository.*;
  4. public interface CityRepository extends Repository<City, Long> {
  5. Page<City> findAll(Pageable pageable);
  6. City findByNameAndStateAllIgnoringCase(String name, String state);
  7. }

Spring Data JPA存储库支持三种不同的引导模式:默认,延迟和延迟。要启用延迟引导或延迟引导,请将spring.data.jpa.repositories.bootstrap-mode属性分别设置为deferredlazy。当使用延迟或懒惰引导时,自动配置的EntityManagerFactoryBuilder将使用上下文的AsyncTaskExecutor(如果有)作为引导执行器。如果存在多个,applicationTaskExecutor将使用一个命名的。

我们几乎没有刮过Spring Data JPA的表面。有关完整的详细信息,请参见Spring Data JPA参考文档

11.3.3 创建和删除JPA数据库

默认情况下,当您使用嵌入式数据库(H2,HSQL或Derby)时,才会自动创建JPA数据库。您可以使用spring.jpa.*属性来显式配置JPA设置。例如,要创建和删除表,可以将以下行添加到中application.properties
spring.jpa.hibernate.ddl-auto =创建-放置

Hibernate自己的内部属性名称是(如果您记得更好)hibernate.hbm2ddl.auto。您可以通过使用spring.jpa.properties.*(与其他Hibernate本机属性一起)设置它(将前缀添加到实体管理器之前先删除前缀)。下面的行显示了为Hibernate设置JPA属性的示例:

spring.jpa.properties.hibernate.globally_quoted_identifiers = true
在前面的示例中的线穿过的一个值truehibernate.globally_quoted_identifiers属性设置为休眠实体管理器。
默认情况下,DDL执行(或验证)推迟到ApplicationContext开始执行之前。还有一个spring.jpa.generate-ddl标志,但是如果激活了Hibernate自动配置,则不会使用它,因为ddl-auto设置更细粒度。

11.3.4 在视图中打开EntityManager

如果您正在运行Web应用程序,则默认情况下,Spring Boot注册OpenEntityManagerInViewInterceptor以应用“在视图中打开EntityManager”模式,以允许在Web视图中进行延迟加载。如果你不希望这种行为,你应该设置spring.jpa.open-in-viewfalseapplication.properties

11.4 Spring Data JDBC

Spring Data包括对JDBC的存储库支持,并将自动为上的方法生成SQL CrudRepository。对于更高级的查询,@Query提供了注释。
当必要的依赖项位于类路径上时,Spring Boot将自动配置Spring Data的JDBC存储库。可以将它们添加到您的项目中,而只需依赖于spring-boot-starter-data-jdbc。如有必要,您可以通过向应用程序中添加@EnableJdbcRepositories注释或JdbcConfiguration子类来控制Spring Data JDBC的配置。

有关Spring Data JDBC的完整详细信息,请参考参考文档

11.5 使用H2的Web控制台

H2数据库提供了一个基于浏览器的控制台是春天开机都能自动为您配置。满足以下条件时,将自动配置控制台:

  • 您正在开发基于servlet的Web应用程序。
  • com.h2database:h2 在类路径上。
  • 您正在使用Spring Boot的开发人员工具。 | | 如果您不使用Spring Boot的开发人员工具,但仍想使用H2的控制台,则可以将spring.h2.console.enabled属性配置为true。 | | :—-: | —- |
H2控制台仅在开发期间使用,因此您应注意确保spring.h2.console.enabled不在true生产环境中使用。

11.5.1 更改H2控制台的路径

默认情况下,控制台位于/h2-console。您可以使用spring.h2.console.path属性来自定义控制台的路径。

11.6 使用jOOQ

jOOQ面向对象查询(jOOQ)是Data Geekery的流行产品,它可以从数据库中生成Java代码,并允许您通过其流畅的API来构建类型安全的SQL查询。商业版和开源版都可以与Spring Boot一起使用。

11.6.1 代码生成

为了使用jOOQ类型安全查询,您需要从数据库架构中生成Java类。您可以按照jOOQ用户手册中的说明进行操作。如果您使用jooq-codegen-maven插件,并且还使用spring-boot-starter-parent“父POM”,则可以安全地忽略插件的<version>标签。您还可以使用Spring Boot定义的版本变量(例如h2.version)来声明插件的数据库依赖关系。以下清单显示了一个示例:

  1. <plugin>
  2. <groupId>org.jooq</groupId>
  3. <artifactId>jooq-codegen-maven</artifactId>
  4. <executions>
  5. ...
  6. </executions>
  7. <dependencies>
  8. <dependency>
  9. <groupId>com.h2database</groupId>
  10. <artifactId>h2</artifactId>
  11. <version>${h2.version}</version>
  12. </dependency>
  13. </dependencies>
  14. <configuration>
  15. <jdbc>
  16. <driver>org.h2.Driver</driver>
  17. <url>jdbc:h2:~/yourdatabase</url>
  18. </jdbc>
  19. <generator>
  20. ...
  21. </generator>
  22. </configuration>
  23. </plugin>

11.6.2 使用DSLContext

jOOQ提供的流畅的API通过该org.jooq.DSLContext接口启动。Spring Boot将a自动配置DSLContext为Spring Bean并将其连接到您的应用程序DataSource。要使用DSLContext,可以使用@Autowire它,如以下示例所示:

  1. @Component
  2. public class JooqExample implements CommandLineRunner {
  3. private final DSLContext create;
  4. @Autowired
  5. public JooqExample(DSLContext dslContext) {
  6. this.create = dslContext;
  7. }
  8. }
jOOQ手册倾向于使用名为的变量create来保存DSLContext

然后,您可以使用DSLContext构造查询,如以下示例所示:

  1. public List<GregorianCalendar> authorsBornAfter1980() {
  2. return this.create.selectFrom(AUTHOR)
  3. .where(AUTHOR.DATE_OF_BIRTH.greaterThan(new GregorianCalendar(1980, 0, 1)))
  4. .fetch(AUTHOR.DATE_OF_BIRTH);
  5. }

11.6.3 jOOQ SQL方言

除非spring.jooq.sql-dialect配置了该属性,否则Spring Boot会确定要用于数据源的SQL语言。如果Spring Boot无法检测到方言,则使用DEFAULT

Spring Boot只能自动配置开源版本的jOOQ支持的方言。

11.6.4 定制jOOQ

通过定义自己的@Bean定义(可以在Configuration创建jOOQ时使用)可以实现更高级的自定义。您可以为以下jOOQ类型定义bean:

  • ConnectionProvider
  • ExecutorProvider
  • TransactionProvider
  • RecordMapperProvider
  • RecordUnmapperProvider
  • Settings
  • RecordListenerProvider
  • ExecuteListenerProvider
  • VisitListenerProvider
  • TransactionListenerProvider

org.jooq.Configuration @Bean如果要完全控制jOOQ配置,也可以创建自己的。

11.7 使用R2DBC

响应式关系数据库连接(R2DBC)项目将响应式编程API引入关系数据库。R2DBCio.r2dbc.spi.Connection提供了使用非阻塞数据库连接的标准方法。连接是通过来提供的ConnectionFactoryDataSource与jdbc相似。
ConnectionFactory配置由中的外部配置属性控制spring.r2dbc.*。例如,您可以在中声明以下部分application.properties
物产
Yaml

  1. spring.r2dbc.url=r2dbc:postgresql://localhost/test
  2. spring.r2dbc.username=dbuser
  3. spring.r2dbc.password=dbpass
您不需要指定驱动程序类名称,因为Spring Boot从R2DBC的Connection Factory发现中获取驱动程序。
至少应提供网址。在URL中指定的信息优先于个人的特性,即nameusernamepassword和池选项。
“操作方法”部分包括有关如何初始化数据库的部分

要自定义由a创建的连接ConnectionFactory,即设置不需要(或无法)在中央数据库配置中配置的特定参数,可以使用ConnectionFactoryOptionsBuilderCustomizer @Bean。以下示例显示了如何从应用程序配置中获取其余选项的同时手动覆盖数据库端口:

  1. @Bean
  2. public ConnectionFactoryOptionsBuilderCustomizer connectionFactoryPortCustomizer() {
  3. return (builder) -> builder.option(PORT, 5432);
  4. }

以下示例显示了如何设置一些PostgreSQL连接选项:

  1. @Bean
  2. public ConnectionFactoryOptionsBuilderCustomizer postgresCustomizer() {
  3. Map<String, String> options = new HashMap<>();
  4. options.put("lock_timeout", "30s");
  5. options.put("statement_timeout", "60s");
  6. return (builder) -> builder.option(OPTIONS, options);
  7. }

ConnectionFactorybean可用时,常规JDBCDataSource自动配置将退出。如果要保留JDBCDataSource自动配置,并且对在反应性应用程序中使用阻塞JDBC API的风险感到满意,请在应用程序中添加@Import(DataSourceAutoConfiguration.class)一个@Configuration类以重新启用它。

11.7.1 嵌入式数据库支持

JDBC支持类似,Spring Boot可以自动配置嵌入式数据库以进行响应式使用。您无需提供任何连接URL。您只需要包括要使用的嵌入式数据库的构建依赖关系,如以下示例所示:

  1. <dependency>
  2. <groupId>io.r2dbc</groupId>
  3. <artifactId>r2dbc-h2</artifactId>
  4. <scope>runtime</scope>
  5. </dependency>
如果在测试中使用此功能,则可能会注意到,整个测试套件将重用同一数据库,而不管您使用的应用程序上下文的数量如何。如果要确保每个上下文都有一个单独的嵌入式数据库,则应设置spring.r2dbc.generate-unique-nametrue

11.7.2 使用DatabaseClient

一个DatabaseClientbean是自动配置,你可以@Autowire直接到自己的豆类,如下面的例子:

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.data.r2dbc.function.DatabaseClient;
  3. import org.springframework.stereotype.Component;
  4. @Component
  5. public class MyBean {
  6. private final DatabaseClient databaseClient;
  7. @Autowired
  8. public MyBean(DatabaseClient databaseClient) {
  9. this.databaseClient = databaseClient;
  10. }
  11. // ...
  12. }

11.7.3 Spring Data R2DBC存储库

Spring Data R2DBC存储库是可以定义以访问数据的接口。查询是根据您的方法名称自动创建的。例如,一个CityRepository接口可能声明了findAllByState(String state)一种查找给定州所有城市的方法。
对于更复杂的查询,您可以使用Spring Data的Query注释对方法进行注释。
Spring Data存储库通常从RepositoryCrudRepository接口扩展。如果您使用自动配置,则会从包含主配置类(用@EnableAutoConfiguration或注释的主配置类)的软件包中搜索存储库@SpringBootApplication
以下示例显示了典型的Spring Data存储库接口定义:

  1. package com.example.myapp.domain;
  2. import org.springframework.data.domain.*;
  3. import org.springframework.data.repository.*;
  4. import reactor.core.publisher.Mono;
  5. public interface CityRepository extends Repository<City, Long> {
  6. Mono<City> findByNameAndStateAllIgnoringCase(String name, String state);
  7. }
我们几乎没有刮过Spring Data R2DBC的表面。有关完整的详细信息,请参见Spring Data R2DBC参考文档