SpringBoot文档翻译系列——29.SQL数据源

原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/7606255.html 

因为需要使用到这方面内容,所有对这一部分进行了翻译。

29  使用SQL数据源

  SpringBoot为SQL数据源提供了广泛支持,从直接使用JdbcTemplate的JDBC访问到完整的ORM(关系映射型)框架(例如Hibernate)。String Data提供了一份经典的功能级别,直接从接口创建存储库实现,并使用约定从方法名生成查询。

29.1  配置数据源

  java的javax.sql.DataSource接口提供了一个经典的方法来使用SQL数据源。一般来说,一个数据源需要一个带有验证的URL来创建一个数据库连接。

29.1.1 嵌入式数据库支持

  使用嵌入内存的数据源来开发一个应用很方便。显然,内存嵌入式数据源并不支持持久存储,因此你必须在应用开始的时候进行数据填充,并在应用停止时有丢失数据的准备。

  SpringBoot可以自动配置需要嵌入的数据源:H2、HSQL和Derby等。这并不需要你提供链接URL,仅仅只需要添加对应的数据源依赖即可。

  注意:如果你在你的测试中使用了嵌入式数据库,为防止你的整个测试套件中的所有应用上下文会共用同一个数据源,需要做以下设置:spring.datasource.generate-unique-name=true

  例如:经典的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-jdbc的依赖被spring-boot-starter-data-jpa所导入(言外之意,你无须关心这一点,因为已经被自动导入了)。

  注意:如果因为一些原因,你需要为嵌入式数据源配置URL,一定要记得将该数据源的自动shutdown功能关闭。如果你使用的是H2数据源,你需要配置DB_CLOSE_ON_EXIT=FALSE;如果你使用的是HSQLDB数据源,你需要确保shutdown=true失效。禁用嵌入式数据源的自动shutdown功能之后当数据源被关闭时转由SpringBoot来进行控制,这样一来不必再确保数据源只被一次访问。

29.1.2 连接生产数据库

  生产的数据库也可以进行自动配置,只需要使用一个数据源池。下面是一些实现方式:

  (1)我们一般热衷于HikariCP ,因为它的高性能和高并发性,一般情况下我们都会选择它。
  (2)另外,如果tomcat的数据源池可用,我们也可以选择使用它。
  (3)如果前两个都不能使用,而DBCP2可用的话,我们选择它。

  如果是添加了spring-boot-starter-jdbc或者是spring-boot-starter-data-jpa依赖starter的话,它们会自动添加对HikariCP的依赖。

  注意:你完全可以忽视其实现算法,而使用spring.datasource.type属性来指定连接池。当你的应用正在使用默认的tomcat-jdbc运行在Tomcat容器时,尤其要注意这一点。

  注意:额外的连接池可以通过手动进行配置,如果你自定义了DataSource的Bean实例,那么自动配置将不会生效。

  数据源的配置由外部属性配置文件:spring.datasource.*来配置。例如:你可以在application.properties文件中申明如下配置:

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链接,或者由SpringBoot自动配置一个内嵌数据源(内嵌数据源不需要指定url)

  注意:你一般不需要指定driver-class-name,因为SpringBoot可以从url之中自动识别出大多数数据库的驱动类名。

  注意:要想得到一个数据源池,我们需要确保对应的驱动类是有效的,这项工作需要最先进行验证。例如:如果你设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver的话,那么这个驱动类必须是可被加载的。

  参照DataSourceProperties类可查看更多配置项。不论实际上如何实现,这些都是一些标准的配置项。还可以通过一些带有前缀的指定配置进行微调(例如:spring.datasource.hikari.*、spring.datasource.tomcat.*、spring.datasource.dbcp2.*等)。更多信息请参考你使用的连接池的实现文档。

  例如:如果你使用的是Tomcat连接池,你需要如下额外配置内容:

# Number of ms to wait before throwing an exception if no connection is available.(如果连接无效,等待多久抛出异常)
spring.datasource.tomcat.max-wait=10000

# Maximum number of active connections that can be allocated from this pool at the same time.(连接池中可同时分配的最大连接数量)
spring.datasource.tomcat.max-active=50

# Validate the connection before borrowing it from the pool.(获取池中连接前是否进行连接验证)
spring.datasource.tomcat.test-on-borrow=true

29.1.3 连接一个JNDI数据源

  如果你正在将你的应用部署到一个应用服务器中,你肯能会想要使用JDNI和服务器特性来配置和管理你的数据源。

  spring.datasource.jndi-name属性可被用来替换spring.datasource.url、spring.datasource.username和spring.datasource.password三个属性来达成定位连接一个JNDI数据源的目的。例如:在application.properties文件中进如下配置可以显示如何连接JBoss中定义的数据源。

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

29.2使用Jdbc Template(Jdbc模板)

  Spring中的JdbcTemplate类和NamedParameterJdbcTemplate类可被自动配置,你可以使用@Autowired注解来将其自动配置到自定义的Bean中。

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

  你可以使用spring.jdbc.template.*系列属性自定义一些Template的属性值,例如:

spring.jdbc.template.max-rows=500

  注意:NamedParameterJdbcTemplate在幕后需要使用同一个JdbcTemplate实例,当你定义了超多一个JdbcTemplate实例并且未指定主要 候选对象的情况下,NamedParameterJdbcTemplate将不会被自动配置。

29.3 JPA和Spring Data

  Java持久化API是一个很经典的技术,它可以实现对象到数据源的映射。spring-boot-starter-data-jpa的POM提供了一种快速达成的方式,它提供了一下主要依赖:

    Hibernate——最流行的JPA实现之一

    Spring Data JPA——简化基于JPA的数据源实现

    Spring ORMs——来自Spring框架的核心ORM支持

  注意:这里我们不会深入讨论JPA和Spring Data的详情。你可以通过阅读对应的引用文档来进行详细了解。

29.3.1 Entity Classes(实体类)

  一般情况下,JPA实体类在persistence.xml文件中指定。在SpringBoot中不再需要这个文件,而是使用Entity Scanner(实体类扫描器)来完成同样的功能。默认情况下,所有位于启动配置类(被注解@EnableAutoConfiguration或者@SpringBootApplication标注的类)所在目录之下的包都将会被扫描。

  任何一个使用注解@Entity, @Embeddable或者@MappedSuperclass标注的类都将会被扫描到。下面展示一个经典的实体类样板:

 1 package com.example.myapp.domain;
 2 
 3 import java.io.Serializable;
 4 import javax.persistence.*;
 5 
 6 @Entity
 7 public class City implements Serializable {
 8 
 9     @Id
10     @GeneratedValue
11     private Long id;
12 
13     @Column(nullable = false)
14     private String name;
15 
16     @Column(nullable = false)
17     private String state;
18 
19     // ... additional members, often include @OneToMany mappings
20 
21     protected City() {
22         // no-args constructor required by JPA spec
23         // this one is protected since it shouldn't be used directly
24     }
25 
26     public City(String name, String state) {
27         this.name = name;
28         this.country = country;
29     }
30 
31     public String getName() {
32         return this.name;
33     }
34 
35     public String getState() {
36         return this.state;
37     }
38 
39     // ... etc
40 
41 }

  注意:你可以使用@EntityScan注解来自定义实体扫描器的扫描路径(标注于启动类),详见第78.4节内容

29.3.2 Spring Data JPA Repository

  Spring Data JPA Repository是可以使你定义连接数据的接口。JPA查询可以通过你自定义的方法名自动创建。例如:一个CityRspository接口可以申明一个findAllByState(String state)方法来根据指定state获取所有城市。

  你可以使用Spring Data的查询注解来定义更加复杂的查询。

  Spring Data Repository接口通常继承自Repository或者CrudRepository接口,如果你正在使用自动配置功能,Respository将会在启动配置类所在包及其下级包内被扫描到。

  下面是一个经典的Spring Data Repository:

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

  注意:我们仅仅了解了Spring Data JPA的基础知识,详情查看引导文档(http://projects.spring.io/spring-data-jpa/)

29.3.3 创建和丢弃JPA数据源

  默认情况下,当你使用了一个嵌入式数据库(H2、 HSQL、Derby)时,JPA Repository将会被自动创建。你可以使用spring.jpa.*来进行JPA的相关配置。例如:为了创建和删除表,你可以在application.properties文件中添加如下配置:

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

  注意:Hibernate针对该配置的内部属性为hibernate.hbm2ddl.auto。你可以使用spring.jpa.properties.*的方式协同Hibernate的其他属性进行一起配置,这个前缀会在添加到实体管理器之前被去除,例如:

spring.jpa.properties.hibernate.globally_quoted_identifiers=true

  通过hibernate.globally_quoted_identifiers来到达Hibernate实体管理器。

  默认情况下,DDL执行或者验证会推迟到ApplicationContext启动后执行。还有一个spring.jpa.generate-ddl标志,但如果Hibernate的 autoconfig是活动状态的,则不会使用它,因为ddl-auto设置更具细粒度。

29.3.4 Open EntityManager in View

  如果你正在运行一个web应用,SpringBoot将默认注册OpenEntityManagerInViewInterceptor来服务于"Open EntityManager in View"模式,例如,它将会开启懒加载功能(在web视图中)。如果你不想要这种功能,你可以通过在application.properties中配置spring.jpa.open-in-view=false来达成。

29.3.5 使用H2的web控制台

  H2数据库提供了一个基于浏览器的web控制台,这个可以有SpringBoot自动配置加载。控制台在达成以下条件后将会被自动配置加载:

    你正在开发的是一个web应用

    com.h2database:h2在类路径下

    你正在使用SpringBoot开发者工具(spring-boot-devtools)

  注意:如果你没有正在使用SpringBoot开发者工具,但却想要使用H2的web控制台功能,你可以配置spring.h2.console.enabled=true来达成目的。该功能仅用于开发期间,在应用上生产环境之时,一定要将spring.h2.console.enabled=true配置去掉。

29.4.1 改变H2控制台的路径

  默认情况下H2控制台只在/h2-console路径下有效,你可以通过属性spring.h2.console.path进行自定义H2控制台的路径。

29.4.2 安全化H2控制台

  当Spring Security位于类路径下,并且基本认证功能处于激活状态时,H2控制台将会自动是使用基本认证功能。下面这些属性可被用来自定义安全配置:

    security.user.role

    security.basic.authorize-mode

    security.basic.enabled

29.5 使用jOOQ

  jOOQ(Java Object Oriented Querying:Java面向对象查询)是一个流行的代码生成器(根据数据源生成java代码),并通过其API创建类型安全的SQL查询,其商业版和开源版均被SpringBoot所支持。

29.5.1 代码生成

  为了使用jOOQ的类型安全的查询,你需要根据数据源结构生成Java类。你可以依据 jOOQ user manual(http://www.jooq.org/doc/3.6/manual-single-page/#jooq-in-7-steps-step3)的介绍。如果你正在使用jooq-codegen-maven插件(并且同是在使用spring-boot-starter-parent),你可以省略拆件的<version>标签,你也可以使用SpringBoot来定义版本变量(例如: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>  

29.5.2 使用DSLContext

  jOOQ所提供的API是通过org.jooq.DSLContext接口开启的。SpringBoot将会自定义一个DSLContext(DSL上下文)Bean和你的应用的数据源连接起来,为了使用DSLContext,你需要@Autowired:

 1 @Component
 2 public class JooqExample implements CommandLineRunner {
 3 
 4     private final DSLContext create;
 5 
 6     @Autowired
 7     public JooqExample(DSLContext dslContext) {
 8         this.create = dslContext;
 9     }
10 
11 }

  注意:jOOQ手册倾向于使用名为create的变量来持有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 }

  然后你可以使用DSLContext来构建你的查询。

29.5.3 jOOQ SQL语言

  SpringBoot可以决定是否使用jOOQ SQL语言,除非spring.jooq.sql-dialect属性被设置,如果该语言无法被执行,则该属性一定被设置为DEFAULT了。

  注意:SpringBoot仅仅支持开源版本的jOOQ SQL语言。

29.5.4 自定义jOOQ

  通过自定义@Bean(这些Bean将会在jOOQ的Configuration被创建时使用),你可以获得更多的高级定制功能。你可以使用如下jOOQ类型来定义Bean:

    ConnectionProvider
    TransactionProvider
    RecordMapperProvider
    RecordListenerProvider
    ExecuteListenerProvider
    VisitListenerProvider

  如果你想要完美的控制jOOQ的各项配置,你需要自定义org.jooq.Configuration配置类(使用@Bean注解)。

原文地址:https://www.cnblogs.com/V1haoge/p/7606255.html