# 29\. 使用SQL数据库 Spring Framework 为使用SQL数据库提供了广泛的支持。 从使用JdbcTemplate直接JDBC访问到完成“对象关系映射”技术,如Hibernate。Spring Data提供了额外的功能,直接从接口创建Repository实现,并使用约定从方法名称生成查询。 ### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#291-配置datasource)29.1 配置DataSource Java的javax.sql.DataSource接口提供了使用数据库连接的标准方法。传统上,DataSource使用URL和一些凭据来建立数据库连接。 > 还可以查看更多高级示例的[“操作方法”部分](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#howto-configure-a-datasource),通常可以完全控制DataSource的配置。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2911-嵌入式数据库支持)29.1.1 嵌入式数据库支持 使用内存中嵌入式数据库开发应用程序通常很方便。 显然,内存数据库不提供持久化存储; 您的应用程序启动时,您将需要初始化数据库,并在应用程序结束时丢弃数据。 > [“How-to”部分](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#howto-database-initialization)包含如何初始化数据库 Spring Boot可以自动配置嵌入式 [H2](http://www.h2database.com/),[HSQL](http://hsqldb.org/) 和 [Derby](https://db.apache.org/derby/) 数据库。 您不需要提供任何连接URL,只需将要使用的嵌入式数据库的依赖关系包含进去即可。 > 如果您在测试中使用此功能,您可能会注意到,整个测试套件都会重复使用相同的数据库,而不管您使用的应用程序上下文的数量。 如果要确保每个上下文都有一个单独的嵌入式数据库,您应该将spring.datasource.generate-unique-name设置为true。 例如,典型的POM依赖关系是: ``` org.springframework.boot spring-boot-starter-data-jpa org.hsqldb hsqldb runtime ``` > 对于要自动配置的嵌入式数据库,您需要依赖spring-jdbc。 在这个例子中,它是通过spring-boot-starter-data-jpa传递的。 > 如果由于某种原因配置嵌入式数据库的连接URL,则应注意确保数据库的自动关闭被禁用。 如果你使用H2,你应该使用DB_CLOSE_ON_EXIT=FALSE这样做。 如果您使用HSQLDB,则应确保不使用shutdown=true。 禁用数据库的自动关闭允许Spring Boot控制数据库何时关闭,从而确保在不再需要访问数据库时发生这种情况。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2912-连接到生产环境数据库)29.1.2 连接到生产环境数据库 生产数据库连接也可以使用连接池数据源自动配置。 这是选择具体实现的算法: * 我们更喜欢Tomcat连接池DataSource的性能和并发性,所以如果可用,我们总是选择它。 * 否则,如果HikariCP可用,我们将使用它。 * 如果Tomcat池数据源和HikariCP都不可用,并且如果Commons DBCP可用,我们将使用它,但是我们不建议在生产中使用它,并且不支持它。 * 最后,如果Commons DBCP2可用,我们将使用它。 如果您使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa 的startters,您将自动获得对tomcat-jdbc的依赖。 > 您可以完全绕过该算法,并通过spring.datasource.type属性指定要使用的连接池。 如果您在Tomcat容器中运行应用程序,则默认情况下提供tomcat-jdbc,这一点尤为重要。 > 可以随时手动配置其他连接池。如果您定义自己的DataSource bean,则不会发生自动配置。 DataSource配置由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,否则Spring Boot将尝试自动配置嵌入式数据库。 > 您通常不需要指定驱动程序类名称,因为Spring Boot可以从url为大多数数据库推断出驱动程序名称。 > 对于要创建的池数据源,我们需要能够验证有效的Driver类是否可用,所以我们在做任何事情之前检查它。 即 如果您设置spring.datasource.driver-class-name=com.mysql.jdbc.Driver,那么该类必须可加载。 有关更多支持的选项,请参阅 [DataSourceProperties](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java)。 这些是标准选项,无论实际执行情况如何。 还可以使用各自的前缀(spring.datasource.tomcat.*,spring.datasource.hikari.*和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 ``` #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2913-连接到jndi-datasource)29.1.3 连接到JNDI DataSource 如果要将Spring Boot应用程序部署到应用程序服务器,则可能需要使用应用程序服务器内置功能来配置和管理DataSource,并使用JNDI进行访问。 spring.datasource.jndi-name属性可以用作spring.datasource.url,spring.datasource.username和spring.datasource.password属性的替代方法,以从特定的JNDI位置访问DataSource。 例如,application.properties中的以下部分显示了如何访问JBoss AS定义的DataSource: ``` spring.datasource.jndi-name=java:jboss/datasources/customers ``` ### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#292-使用jdbctemplate)29.2 使用JdbcTemplate Spring的JdbcTemplate和NamedParameterJdbcTemplate类是自动配置的,您可以将它们直接连接到您自己的bean中: ``` 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; } // ... } ``` ### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#293-jpa-和-spring-data)29.3 JPA 和 ‘Spring Data’ Java Persistence API是一种标准技术,可让您将对象映射到关系数据库。 spring-boot-starter-data-jpa POM提供了一种快速入门的方法。 它提供以下关键依赖: * Hibernate - 最受欢迎的JPA实现之一。 * Spring Data JPA - 可以轻松实现基于JPA的存储库。 * Spring ORMs - 来自Spring Framework的核心ORM支持。 > 我们不会在这里介绍太多的JPA或Spring Data的细节。 您可以从[spring.io](http://spring.io)中查看“[使用JPA访问数据](https://spring.io/guides/gs/accessing-data-jpa/)”指南,并阅读[Spring Data JPA](http://projects.spring.io/spring-data-jpa/)和[Hibernate](http://hibernate.org/orm/documentation/)参考文档。 > 默认情况下,Spring Boot使用Hibernate 5.0.x. 但是,如果您愿意,也可以使用4.3.x或5.2.x。 请参考 [Hibernate 4](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-samples/spring-boot-sample-hibernate4) 和 [Hibernate 5.2](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-samples/spring-boot-sample-hibernate52) 示例,看看如何做到这一点。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2931-实体类)29.3.1 实体类 传统上,JPA'Entity'类在persistence.xml文件中指定。 使用Spring Boot此文件不是必需的,而是使用“实体扫描”。 默认情况下,将搜索主配置类下面的所有包(用@EnableAutoConfiguration或@SpringBootApplication注解的类)。 任何用@Entity,@Embeddable或@MappedSuperclass注解的类将被考虑。 典型的实体类将如下所示: ``` 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; // ... additional members, often include @OneToMany mappings protected City() { // no-args constructor required by JPA spec // this one is protected since it shouldn't be used directly } public City(String name, String state) { this.name = name; this.country = country; } public String getName() { return this.name; } public String getState() { return this.state; } // ... etc } ``` > 您可以使用@EntityScan注解自定义实体扫描位置。 请参见[第77.4节“从Spring配置中分离@Entity定义”](http://docs.spring.io/spring-boot/docs/1.5.2.RELEASE/reference/htmlsingle/#howto-separate-entity-definitions-from-spring-configuration)操作方法。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2932-spring-data-jpa-repositories)29.3.2 Spring Data JPA Repositories Spring Data JPA库是可以定义用于访问数据的接口。 JPA查询是从您的方法名称自动创建的。 例如,CityRepository接口可以声明findAllByState(String state)方法来查找给定状态下的所有城市。 对于更复杂的查询,您可以使用Spring数据[查询](http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/Query.html)注解来注解您的方法。 Spring数据存储库通常从Repository或CrudRepository接口扩展。 如果您正在使用自动配置,将从包含主配置类(通过@EnableAutoConfiguration或@SpringBootApplication注解的包)的包中搜索存储库(repositories)。 这是一个典型的Spring数据库: ``` package com.example.myapp.domain; import org.springframework.data.domain.*; import org.springframework.data.repository.*; public interface CityRepository extends Repository { Page findAll(Pageable pageable); City findByNameAndCountryAllIgnoringCase(String name, String country); } ``` > 我们只是触及了Spring Data JPA的表面。 有关完整的详细信息,请查阅其[参考文档](http://projects.spring.io/spring-data-jpa/)。 #### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2933-创建和删除jpa数据库)29.3.3 创建和删除JPA数据库 默认情况下,仅当您使用嵌入式数据库(H2,HSQL或Derby)时才会自动创建JPA数据库。 您可以使用spring.jpa。*属性显式配置JPA设置。 例如,要创建和删除表,您可以将以下内容添加到application.properties中。