• 20220519 Data 1. SQL Databases


    前言

    文档地址

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

    1.1. 配置数据源

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

    1.1.1. 嵌入式数据库支持

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

    Spring Boot 可以自动配置嵌入式 H2HSQLDerby 数据库。您无需提供任何连接 URL 。您只需要包含要使用的嵌入式数据库的构建依赖项即可。如果类路径上有多个嵌入式数据库,请设置 spring.datasource.embedded-database-connection 配置属性以控制使用哪一个。将该属性设置为 none 禁用嵌入式数据库的自动配置。

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

    例如,典型的 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>
    

    您需要依赖 spring-jdbc 才能自动配置嵌入式数据库。在此示例中,它通过 spring-boot-starter-data-jpa 引入。

    如果出于某种原因确实为嵌入式数据库配置了连接 URL ,请确保禁用了数据库的自动关闭功能。如果您使用 H2 ,则应该使用 DB_CLOSE_ON_EXIT=FALSE 。如果使用 HSQLDB ,则应确保未使用 shutdown=true 。通过禁用数据库的自动关闭功能,Spring Boot 可以控制何时关闭数据库,从而确保一旦不再需要访问数据库时就可以执行该操作。

    1.1.2. 连接到生产数据库

    生产数据库连接也可以使用池化 DataSource 自动配置。

    1.1.3. DataSource 配置

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

    spring.datasource.url=jdbc:mysql://localhost/test
    spring.datasource.username=dbuser
    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 连接池 ,您可以自定义许多附加设置,如下例所示:

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

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

    1.1.4. 支持的连接池

    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 Starters ,会自动引入 HikariCP

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

    额外的连接池总是可以手动配置,使用 DataSourceBuilder 。如果您定义自己的 DataSource bean ,则不会发生自动配置。DataSourceBuilder 支持以下连接池:

    • HikariCP
    • Tomcat pooling Datasource
    • Commons DBCP2
    • Oracle UCP & OracleDataSource
    • Spring Framework 的 SimpleDriverDataSource
    • H2 JdbcDataSource
    • PostgreSQL PGSimpleDataSource

    1.1.5. 连接到 JNDI DataSource

    如果您将 Spring Boot 应用程序部署到 Application Server ,则可能要使用 Application Server 的内置功能来配置和管理 DataSource ,并使用 JNDI 对其进行访问。

    spring.datasource.jndi-name 属性可以被用来替代 spring.datasource.urlspring.datasource.usernamespring.datasource.password 属性来从一个特定的 JNDI 位置访问 DataSource 。例如,application.properties 以下部分显示了如何访问 JBoss AS 定义的 DataSource:

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

    1.2. 使用 JdbcTemplate

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

    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.* 属性来自定义模板的某些属性,如以下示例所示:

    spring.jdbc.template.max-rows=500
    

    NamedParameterJdbcTemplate 重用相同的 JdbcTemplate

    如果定义了多个 JdbcTemplate ,并且不存在主要候选对象,则不会自动配置 NamedParameterJdbcTemplate

    参考源码:

    org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
    

    1.3. JPA 和 Spring Data JPA

    Java Persistence API 是一种标准技术,可让您将对象“映射”到关系数据库。spring-boot-starter-data-jpa POM 提供了一种快速入门的方法。它提供以下关键依赖项:

    • Hibernate :最流行的 JPA 实现之一
    • Spring Data JPA :帮助您实现基于 JPA 的存储库
    • Spring ORM :来自 Spring Framework 的核心 ORM 支持

    1.3.1. Entity 类

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

    任何类标注了 @Entity@Embeddable 或者 @MappedSuperclass 被认为是 实体(Entity)。典型的实体类:

    import java.io.Serializable;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.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
    
    }
    

    您可以使用 @EntityScan 注解自定义实体扫描位置。请参阅 Separate @Entity Definitions from Spring Configuration

    1.3.2. Spring Data JPA 存储库

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

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

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

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

    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 存储库支持三种不同的引导模式:defaultdeferredlazy 。要启用 deferredlazy 引导,请将 spring.data.jpa.repositories.bootstrap-mode 属性分别设置为 deferredlazy 。当使用 deferredlazy 引导时,自动配置的 EntityManagerFactoryBuilder 将使用上下文的 AsyncTaskExecutor(如果有)作为引导执行器。如果存在多个,将使用命名为 applicationTaskExecutor 的那个。

    使用 deferredlazy 引导时,请确保在应用上下文引导阶段之后推迟对 JPA 基础架构的任何访问。您可以使用 SmartInitializingSingleton 来调用任何需要 JPA 基础结构的初始化。对于作为 Spring bean 创建的 JPA 组件(例如转换器),如果有依赖关系,请使用 ObjectProvider 来延迟解析

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

    1.3.3. Spring Data Envers 存储库

    如果 Spring Data Envers 可用,JPA 存储库会自动配置为支持典型的 Envers 查询。

    要使用 Spring Data Envers,请确保您的存储库从 RevisionRepository 扩展:

    import org.springframework.boot.docs.data.sql.jpaandspringdata.entityclasses.Country;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.repository.Repository;
    import org.springframework.data.repository.history.RevisionRepository;
    
    public interface CountryRepository extends RevisionRepository<Country, Long, Integer>, Repository<Country, Long> {
    
        Page<Country> findAll(Pageable pageable);
    
    }
    

    有关更多详细信息,请查看 Spring Data Envers 参考文档

    1.3.4. 创建和删除 JPA 数据库

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

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

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

    spring.jpa.properties.hibernate.globally_quoted_identifiers = true
    

    在前面的示例中为 Hibernate 实体管理器将 hibernate.globally_quoted_identifiers 属性赋值 true

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

    1.3.5. 在视图中打开 EntityManager

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

    1.4. Spring Data JDBC

    Spring Data 包括对 JDBC 的存储库支持,并将自动为 CrudRepository 上的方法生成 SQL 。对于更高级的查询,提供了 @Query 注解。

    当必要的依赖项位于类路径上时,Spring Boot 将自动配置 Spring Data 的 JDBC 存储库。可以将它们添加到您的项目中,而只需依赖 spring-boot-starter-data-jdbc 。如有必要,您可以通过向应用程序中添加 @EnableJdbcRepositories 注解或 JdbcConfiguration 子类来控制 Spring Data JDBC 的配置。

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

    1.5. 使用 H2 的 Web 控制台

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

    如果您不使用 Spring Boot 的开发者工具,但仍想使用 H2 的控制台,则可以将 spring.h2.console.enabled 属性配置为 true

    H2 控制台仅在开发期间使用,因此您应注意确保不在生产环境中使用 spring.h2.console.enabled=true

    1.5.1. 更改 H2 控制台的路径

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

    1.5.2. 在安全应用程序中访问 H2 控制台

    H2 控制台使用框架(frames),并且仅用于开发,不实施 CSRF 保护措施。如果您的应用程序使用 Spring Security ,则需要将其配置为

    • 禁用针对控制台请求的 CSRF 保护
    • 将标头设置为 X-Frame-Options 对于来自 SAMEORIGIN 控制台的响应

    有关 CSRF 和标头 X-Frame-Options 的更多信息可以在 Spring Security 参考指南中找到。

    在简单的设置中,SecurityFilterChain 可以使用如下所示:

    @Profile("dev")
    @Configuration(proxyBeanMethods = false)
    public class DevProfileSecurityConfiguration {
    
        @Bean
        @Order(Ordered.HIGHEST_PRECEDENCE)
        SecurityFilterChain h2ConsoleSecurityFilterChain(HttpSecurity http) throws Exception {
            return http.requestMatcher(PathRequest.toH2Console())
                    // ... configuration for authorization
                    .csrf().disable()
                    .headers().frameOptions().sameOrigin().and()
                    .build();
        }
    
    }
    

    H2 控制台仅供开发期间使用。在生产中,禁用 CSRF 保护或允许网站使用框架(frames)可能会造成严重的安全风险

    当控制台的路径已被自定义时,PathRequest.toH2Console() 也会返回正确的请求匹配器。

    1.6. 使用 jOOQ

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

    1.6.1. 代码生成

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

    <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>
    

    1.6.2. 使用 DSLContext

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

    import java.util.GregorianCalendar;
    import java.util.List;
    
    import org.jooq.DSLContext;
    
    import org.springframework.stereotype.Component;
    
    import static org.springframework.boot.docs.data.sql.jooq.dslcontext.Tables.AUTHOR;
    
    @Component
    public class MyBean {
    
        private final DSLContext create;
    
        public MyBean(DSLContext dslContext) {
            this.create = dslContext;
        }
    
    
    }
    

    jOOQ 手册倾向于使用名为 create 的变量来保存 DSLContext

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

    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);
    

    1.6.3. jOOQ SQL 方言

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

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

    1.6.4. 自定义 jOOQ

    通过定义自己的 DefaultConfigurationCustomizer @Bean 定义可以实现更高级的自定义,该 bean 将在创建 org.jooq.Configuration @Bean 之前被调用。这优先于自动配置应用的任何内容。

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

    1.7. 使用 R2DBC todo

    反应式关系数据库连接 ( R2DBC ) 项目将反应式编程 API 引入关系数据库。

  • 相关阅读:
    网页挂马实验
    基于内核网络过滤实验
    基与内核的键盘记录实验
    网络蠕虫病毒代码分析
    脚本病毒编写实验
    病毒查找与清除实验
    木马分析(植入分析)实验
    木马分析(控制分析)实验
    木马分析(隐藏分析)实验
    移动存储型病毒分析实验
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/16354171.html
Copyright © 2020-2023  润新知