SQL数据库

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

配置数据源

Java的javax.sql.DataSource接口提供了一种使用数据库连接的标准方法。传统上,’DataSource’使用URL一些凭证来建立数据库连接。

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

嵌入式数据库支持

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

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

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

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

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

1
2
3
4
5
6
7
8
9
<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>

您需要依赖于spring-jdbc自动配置嵌入式数据库。在这个例子中,它被传递过来 spring-boot-starter-data-jpa

如果由于某种原因,您确实为嵌入式数据库配置了连接URL,请注意确保禁用数据库的自动关闭。如果你使用H2,你应该DB_CLOSE_ON_EXIT=FALSE这样做。如果使用HSQLDB,则应确保shutdown=true未使用HSQLDB 。禁用数据库的自动关闭可以在数据库关闭时进行Spring Boot控制,从而确保在不再需要访问数据库时发生。

连接到生产数据库

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

  1. 我们更喜欢HikariCP的性能和并发性。如果HikariCP可用,我们总是选择它。
  2. 否则,如果Tomcat池DataSource可用,我们将使用它。
  3. 如果HikariCP和Tomcat池化数据源都不可用,并且 Commons DBCP2可用,我们就会使用它。

如果您使用spring-boot-starter-jdbcspring-boot-starter-data-jpa启动器,您将自动获得依赖HikariCP

您可以完全绕过该算法,并通过设置spring.datasource.type属性指定要使用的连接池。如果您在Tomcat容器中运行应用程序tomcat-jdbc(默认情况下提供),这一点尤为重要。

始终可以手动配置其他连接池。如果您定义自己的DataSourcebean,则不会进行自动配置。

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

1
2
3
4
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

您至少应该通过设置spring.datasource.url 属性来指定URL 。否则,Spring Boot会尝试自动配置嵌入式数据库。

您通常不需要指定driver-class-name,因为Spring Boot可以从大多数数据库推断它url

对于DataSource要创建的池,我们需要能够验证有效的 Driver类是否可用,因此我们在执行任何操作之前检查它。换句话说,如果你设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,那么该类必须是可加载的。

有关DataSourceProperties 更多支持的选项,请参阅 。无论实际实施如何,这些都是标准选项。也可以微调实现特定的设置,使用各自的前缀(spring.datasource.hikari.*spring.datasource.tomcat.*,和spring.datasource.dbcp2.*)。有关更多详细信息,请参阅您正在使用的连接池实现的文档。

例如,如果使用 Tomcat连接池,则可以自定义许多其他设置,如以下示例所示:

1
2
3
4
5
6
7
8
#如果没有可用连接,则在抛出异常之前要等待的ms数。
spring.datasource.tomcat.max-wait = 10000

#可以同时从该池分配的最大活动连接数。
spring.datasource.tomcat.max-active = 50

#在从池中借用连接之前验证连接。
spring.datasource.tomcat.test-on-borrow = true

连接到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

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

使用JdbcTemplate

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

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {
private final JdbcTemplate jdbcTemplate;
@Autowired
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// ...
}

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

1
spring.jdbc.template.max-rows=500

NamedParameterJdbcTemplate重复使用相同的JdbcTemplate幕后情况。如果JdbcTemplate定义了多个且没有主要候选项,NamedParameterJdbcTemplate则不会自动配置。

JPA和Spring Data JPA

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

  • Hibernate:最受欢迎的JPA实现之一。
  • Spring Data JPA:使实现基于JPA的存储库变得容易。
  • Spring ORMs:Spring Framework的核心ORM支持。

我们不会在这里详细介绍JPA或Spring Data。您可以按照“访问数据与JPA” 从指导spring.io并宣读了春天的数据JPAHibernate的参考文档。

实体类

传统上,JPA“实体”类在persistence.xml文件中指定。使用Spring Boot,此文件不是必需的,而是使用“实体扫描”。默认情况下,将搜索主配置类(注释为@EnableAutoConfiguration或者@SpringBootApplication)下的所有包 。

任何类别标注了@Entity@Embeddable或者@MappedSuperclass被认为是。典型的实体类类似于以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

@Id
@GeneratedValue
private Long id;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String state;

// ...其他成员,通常包括@OneToMany映射

protected City() {
//JPA规范要求的no-args构造函数
//这个是受保护的,因为它不应该直接使用
}

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
}

您可以使用@EntityScan注释自定义实体扫描位置。请参阅“ 第84.4节,“从Spring配置中分离@Entity定义”操作方法”

Spring Data JPA存储库

Spring Data JPA存储库是您可以定义以访问数据的接口。JPA查询是从您的方法名称自动创建的。例如, CityRepository接口可能会声明一种findAllByState(String state)方法来查找给定状态中的所有城市。

对于更复杂的查询,您可以使用Spring Data的Query注释来注释您的方法 。

Spring Data存储库通常从RepositoryCrudRepository 接口扩展 。如果使用自动配置,则会从包含主配置类(带有@EnableAutoConfiguration或标注的@SpringBootApplication)的包中搜索存储库 。

以下示例显示了典型的Spring Data存储库接口定义:

1
2
3
4
5
6
7
8
9
package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}

Spring Data JPA存储库支持三种不同的引导模式:default,deferred和lazy。要启用延迟或延迟引导,请分别设置spring.data.jpa.repositories.bootstrap-modedeferredlazy。使用延迟或延迟引导时,自动配置EntityManagerFactoryBuilder 将使用上下文(AsyncTaskExecutor如果有)作为引导程序执行程序。如果存在多个,则使用命名的那个applicationTaskExecutor

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

创建和删除JPA数据库

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

1
spring.jpa.hibernate.ddl-auto=create-drop

Hibernate自己的内部属性名称(如果你碰巧记得更好)是hibernate.hbm2ddl.auto。您可以使用spring.jpa.properties.*(在将它们添加到实体管理器之前剥离前缀)来设置它以及其他Hibernate本机属性。以下行显示了为Hibernate设置JPA属性的示例:

1
spring.jpa.properties.hibernate.globally_quoted_identifiers=true

在前面的示例中的线穿过的一个值truehibernate.globally_quoted_identifiers属性设置为休眠实体管理器。

默认情况下,DDL执行(或验证)将延迟到ApplicationContext 启动。还有一个spring.jpa.generate-ddl标志,但如果Hibernate自动配置处于活动状态,则不会使用该标志,因为ddl-auto设置更精细。

在View中打开EntityManager

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

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的完整详细信息,请参阅 参考文档

使用H2的Web控制台

H2数据库提供了一个 基于浏览器的控制台,Spring启动即可自动配置。满足以下条件时,将自动配置控制台:

如果您没有使用Spring Boot的开发人员工具但仍希望使用H2的控制台,则可以spring.h2.console.enabled使用值配置属性true

H2控制台仅用于开发期间,因此您应该注意确保spring.h2.console.enabled在生产中不要设置为true

更改H2控制台的路径

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

使用jOOQ

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

代码生成

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

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

使用DSLContext

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

1
2
3
4
5
6
7
8
9
10
@Component
public class JooqExample implements CommandLineRunner {

private final DSLContext create;

@Autowired
public JooqExample(DSLContext dslContext) {
this.create = dslContext;
}
}

jOOQ手册倾向于使用一个名为createhold的变量DSLContext

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

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

jOOQ SQL方言

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

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

自定义jOOQ

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

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

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