Spring Data JPA-属性详解 JdbcProperties 和 DataSourceProperties

3,471 阅读3分钟

这是我参与11月更文挑战的第 12 天,活动详情查看:2021最后一次更文挑战

最近查了一个 spring data jpa 的问题,其实也不能算是框架层面的问题,准确说是配置;因为之前没有怎么使用过 spring data jpa(更多是 mybatis 或者自研 orm 组件),所以期望通过本篇来记录下 spring data jpa 的配置。

本篇从配置源码开始,先直观的了解 spring data jpa 自己有哪些配置,然后会结合具体的 case 来描述各个配置的作用;同时也对类似 spring.datasource.* 的配置也做简单介绍,不要再傻傻分不清了。

分为 一、二 和 综合实践三部分,本篇为第一部分 jdbc 配置相关

jdbc 配置和 jpa 配置

在没有使用之前,一直会认为 datasource 的配置,如:url, class-drive-name 等也是在 spring data jpa 下,看起来还不是。换个角度想了下,url, class-drive-name 这些属于 jdbc 的配置,并非是 orm 的配置,所以也就理所应当了。下面分别看看 JpaPropertiesHibernateProperties 以及 jdbc 的配置。

jdbc 配置

在 spring 的 jdbc 代码模块中,jdbc 的配置包括两个:

  • JdbcProperties: prefix 为 spring.jdbc.*
  • DataSourceProperties: prefix 为 spring.datasource.*

JdbcProperties

下面是 JdbcProperties,对于这几个配置,着实看起来有点陌生

@ConfigurationProperties(prefix = "spring.jdbc")
public class JdbcProperties {
   private final Template template = new Template();
   public static class Template {
      private int fetchSize = -1;
      private int maxRows = -1;
      @DurationUnit(ChronoUnit.SECONDS)
      private Duration queryTimeout;

JdbcProperties 配置通过代码分析来看,目前只有在 JdbcTemplate 中使用了;也就是说,如果你的项目中没有使用 JdbcTemplate 的话,那 spring.jdbc.template.* 是无用的。抛个问题:如果使用 JdbcTemplate, 并且将 queryTimeout 配置成 -1 是不是一定会超时?为 0 呢?答案肯定是

jdbc 的这几个参数从代码看,最终都是为底层 Statement 服务的,这里不具体介绍执行过程及原理;这里放一个之前看到的一篇查询超时问题的排查,以供各位理解:关于jdbc的setQueryTimeout() 的bug和Query execution was interrupted 的调查

  • fetchSize: 从数据库和结果集查询时,每次拉取指定 fetchSize 大小的数据,循环去取,直到取完。
  • maxRows:底层 Statement 对象生成的所有 ResultSet 对象可以包含的最大行数限制,最大以后的数据会被丢掉;这个参数设置应该是为了避免在结果集非常大的时候导致内存扛不住。

DataSourceProperties

这个比较容易理解,就是数据源配置,常见的 url, driverClassName 都是在这里配置的。

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
   private ClassLoader classLoader;
   // datasource 名字,如果使用 embedded database,默认名是 "testdb"
   private String name;
    // 是否要随机创建一个 datasource name
   private boolean generateUniqueName = true;
   // 具体 connection pool 实现类的全限定名
   private Class<? extends DataSource> type;
   // 具体 JDBC driver 实现类的全限定名
   private String driverClassName;
   /**
    * JDBC URL of the database.
    */
   private String url;

   /**
    * Login username of the database.
    */
   private String username;

   /**
    * Login password of the database.
    */
   private String password;

   /**
    * 数据源的JNDI位置,如果使用这个,url,username 这些就不需要了。(没用过)
    */
   private String jndiName;
   // 初始化模式,比如是否使用可用的 DDL and DML 脚本
   private DataSourceInitializationMode initializationMode = DataSourceInitializationMode.EMBEDDED;

   /**
    * 在DDL 或 DML脚本中使用的平台 (such as schema-${platform}.sql or
    * data-${platform}.sql).
    */
   private String platform = "all";
   
   // Schema (DDL) 脚本的资源位置.
   private List<String> schema;
   private String schemaUsername;
   private String schemaPassword;
   
   // Data (DML) 脚本资源位置.
   private List<String> data;
   private String dataUsername;
   private String dataPassword;
   
   // 是否在初始化数据库时发生错误时停止。
   private boolean continueOnError = false;
   
   // SQL初始化脚本中的语句分隔符。
   private String separator = ";";
   
   // 编码格式
   private Charset sqlScriptEncoding;

一般项目中,常见的配置大概如下,应该是对于任何 spring 配置数据源来说,这个都是必不可少的:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=
spring.datasource.url=jdbc:mysql://localhost:3306/glmapper?createDatabaseIfNotExist=true&xxx=xxx

配置初始化的 DDL 和 DML

spring.datasource.schema=schema.sql
spring.datasource.data=data.sql

如果配置中指定了 platform

spring.datasource.platform=test

那么需要将 配置初始化的 DDL 和 DML 修改为

spring.datasource.schema=schema-test.sql
spring.datasource.data=data-test.sql

否则会出现找不到 resource 的报错,如下:

Invalid value 'schema.sql' for configuration property 'spring.datasource.schema' (originating from 'class path resource [application.properties] - 7:26'). Validation failed for the following reason:

The specified resource does not exist.

小结

本篇主要介绍 Spring Data JPA 配置部分关于 jdbc 的配置,如有问题欢迎指正。