Spring Data JPA 从入门到精通~默认数据源的讲解

37 篇文章 10 订阅

默认数据源

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456

但是在实际工作中不可能这么简单,因为会用其他数据源,而不是用的默认数据源。我们先来一步一步了解一下,一起来开启探索它默认的数据源之旅吧。

通过三种方法来查看默认的 DataSource 是什么

(1)日志法:在 application.properties 增加如下配置

logging.level.org.springframework=DEBUG

然后当我们启动成功之后,通过开发工具 Intellij IDEA 的 Debug 的 Console 控制台,搜索“DataSource”,找到了如下日志,发现它默认是 JDBC 的 Pool 的 DataSource。

spring.datasource.type=com.zaxxer.hikari.HikariDataSource,需要注意的是这是 Spring Boot 2.0 里面的新特性,代替了 1.5** 版本里面的 org.apache.tomcat.jdbc.pool.DataSource 的数据源,hikari 的口碑可以性能测试行业内的口碑逐渐代替了 Tomcat 的 datasource。

(2)Debug 方法:在 manager 里面的如下代码

在“userRepository.findByLastName(names);” 设置一个断点,然后请求一个 URL 让断点进来,然后通过开发工具 Intellij IDEA 的 Debug 的 Memory View 视图,里面搜索

也能发现 DataSource,然后双击就能看到我们想看的内容。

(3)最原理的方法、最常用的、原理分析方法

回到 QuickStartApplication,单击 @SpringBootApplication 查看其源码关键部分如下:

@SpringBootConfiguration
    @EnableAutoConfiguration
    public @interface SpringBootApplication {......}

打开 @EnableAutoConfiguration 所在 JAR 包,打开 spring-boot-autoconfigure-2.0.0.RELEASE.jar/META-INF/spring.factories 文件,发现如下内容:

//# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
......
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration

打开 JpaRepositoriesAutoConfiguration 类,内容如下:
@Configuration
@ConditionalOnBean(DataSource.class)
@ConditionalOnClass(JpaRepository.class)
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class,
        JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@Import(JpaRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration {
}

这时候可以发现,如果使用了 Spring Boot 的注解方式和传统的 XML 配置方式是有优先级的,如果配置了 XML 中的 JpaRepositoryFactoryBean,那么就会沿用 XML 配置的一整套,而通过 @ConditionalOnMissingBean 这个注解来判断,就不会加载 Spring Boot 的 JpaRepositoriesAutoConfiguration 此类的配置,还有就是前提条件 DataSource 和 JpaRepository 必须有相关的 Jar 存在。

打开 HibernateJpaAutoConfiguration 类:

@Configuration
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class })
@Conditional(HibernateEntityManagerCondition.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {......}

这个时候发现了 DataSourceAutoConfiguration 的配置类即 datasource 的配置内容有哪些?

打开 DataSourceAutoConfiguration,此时发现了我们最关键的类出现了。

@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
        DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {......}

先看 DataSourcePoolMetadataProvidersConfiguration 类吧,内容如下:

@Configuration
public class DataSourcePoolMetadataProvidersConfiguration {
    //tomcat.jdbc.pool.DataSource前提条件需要引入tomcat-jdbc.jar
    @Configuration
    @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class)
    static class TomcatDataSourcePoolMetadataProviderConfiguration {
        @Bean
        public DataSourcePoolMetadataProvider tomcatPoolDataSourceMetadataProvider() {
            return (dataSource) -> {
                if (dataSource instanceof org.apache.tomcat.jdbc.pool.DataSource) {
                    return new TomcatDataSourcePoolMetadata(
                            (org.apache.tomcat.jdbc.pool.DataSource) dataSource);
                }
                return null;
            };
        }
    }
    //HikariDataSource.class前提需要引入HikariCP-2.7.8.jar
    @Configuration
    @ConditionalOnClass(HikariDataSource.class)
    static class HikariPoolDataSourceMetadataProviderConfiguration {
        @Bean
        public DataSourcePoolMetadataProvider hikariPoolDataSourceMetadataProvider() {
            return (dataSource) -> {
                if (dataSource instanceof HikariDataSource) {
                    return new HikariDataSourcePoolMetadata(
                            (HikariDataSource) dataSource);
                }
                return null;
            };
        }
    }
    //CommonsDbcp 数据源,前提也是需要引入CommonsDbcp**.jar
    @Configuration
    @ConditionalOnClass(BasicDataSource.class)
    static class CommonsDbcp2PoolDataSourceMetadataProviderConfiguration {
        @Bean
        public DataSourcePoolMetadataProvider commonsDbcp2PoolDataSourceMetadataProvider() {
            return (dataSource) -> {
                if (dataSource instanceof BasicDataSource) {
                    return new CommonsDbcp2DataSourcePoolMetadata(
                            (BasicDataSource) dataSource);
                }
                return null;
            };
        }
    }
}

通过查看它的代码可发现,Spring Boot 为我们的 DataSource 提供了最常见的三种默认配置:

  • HikariDataSource
  • Tomcat 的 JDBC
  • Apache 的 dbcp

而最终用哪个?就看你引用了哪个 datasoure 的 jar 包了。因为开篇的案例用的是 Spring Boot 2.0 的默认配置,而 2.0 放弃了默认引用的 Tomcat 的容器,而选用了 HikariDataSource 的配置,成为了 Java 语言里面公认的好的 data source,所以默认用的是 Hikari 的 DataSource 及其 HikariDataSourcePoolMetadata 连接池。当我们引用了 Jetty 或者 netty 等容器,连接池和 datasource 的实现方式也会跟着变的。

Datasource 和 JPA 都有哪些配置属性

我们接着上面的类 DataSourceAutoConfiguration,通过 @EnableConfigurationProperties(DataSourceProperties.class) 找到了 datasource 该如何配置,打开 DataSourceProperties 源码:

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties
      implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
/**
 * Name of the datasource.
 */
private String name = "testdb";
/**
 * Generate a random datasource name.
 */
private boolean generateUniqueName;
/**
 * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
 */
private String driverClassName;
/**
 * JDBC url of the database.
 */
private String url;
/**
 * Login user of the database.
 */
private String username;
/**
 * Login password of the database.
 */
private String password;
/**
 * JNDI location of the datasource. Class, url, username & password are ignored when
 * set.
 */
private String jndiName;
......//如果还有一些特殊的配置直接看这个类的源码即可。
}

看到了配置数据的关键的几个属性的配置,及其一共有哪些属性值可以去配置。@ConfigurationProperties(prefix = "spring.datasource") 这个告诉我们 application.properties 里面的 datasource 相关的配置必须有 spring.datasource 开头,这样当启动的时候 DataSourceProperties 就会自动加载进来 datasource 的一切配置。正如我们前面配置的一样:

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=jack
spring.datasource.password=jack123

......这里省略了一些其他datasource的key配置。

其实到这里如果自定义配置时也可以学习 Spring Data 的这种 properteis 的加载方式自定义**Properties.java,包括 DataSource 的配置方法,可以借鉴当时写的framework.jar。

JpaBaseConfiguration

我们回过头来再来看 HibernateJpaAutoConfiguration 的父类 JpaBaseConfiguration 打开关键内容如下:

@EnableConfigurationProperties(JpaProperties.class)
@Import(DataSourceInitializedPublisher.Registrar.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware {
   private final DataSource dataSource;
   private final JpaProperties properties;
......}

这个时候发现了 JpaProperties 类:

@ConfigurationProperties(prefix = "spring.jpa")
public class JpaProperties {
  //jpa原生的一些特殊属性
   private Map<String, String> properties = new HashMap<String, String>();
   //databasePlatform名字,默认和Database一样。
   private String databasePlatform;
   //数据库平台MYSQL、DB2、H2......
   private Database database;
   //是否根据实体创建Ddl
   private boolean generateDdl = false;
   //是否显示sql,默认不显示
   private boolean showSql = false;
   private Hibernate hibernate = new Hibernate();
......
}

此时再打开 Hibernate 类:

public static class Hibernate {
private String ddlAuto;
/**
 * Use Hibernate's newer IdentifierGenerator for AUTO, TABLE and SEQUENCE. This is
 * actually a shortcut for the "hibernate.id.new_generator_mappings" property.
 * When not specified will default to "false" with Hibernate 5 for back
 * compatibility.
 */
private Boolean useNewIdGeneratorMappings;
@NestedConfigurationProperty
private final Naming naming = new Naming();
......//我们看到Hibernate类就这三个属性。
}

再打开 Naming 源码看一下命名规范:

public static class Naming {
   private static final String DEFAULT_HIBERNATE4_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy";
   private static final String DEFAULT_PHYSICAL_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy";
   private static final String DEFAULT_IMPLICIT_STRATEGY = "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy";
   /**
    * Hibernate 5 implicit naming strategy fully qualified name.
    */
   private String implicitStrategy;
   /**
    * Hibernate 5 physical naming strategy fully qualified name.
    */
   private String physicalStrategy;
   /**
    * Hibernate 4 naming strategy fully qualified name. Not supported with Hibernate
    * 5.
    */
   private String strategy;
......}

看到这里面 Naming 命名策略,兼容了 Hibernate4 和 Hibernate5 并且给出了默认的策略,后面章节我们做详细解释。

所以配置文件中关于 JPA 的配置基本上就这些配置项。

spring.jpa.database-platform=mysql
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.type=trace
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.properties.hibernate.jdbc.batch_size=50

Configuration 思路,实战学习方法

其实在实际工作中,若遇到问题,经常看到开发人员去百度进行狂搜,看看怎么配置的,然后试了了半天发现怎么配置都没效果。其实这里给大家提供了一个思路,我们在找配置项的时候,看看源码都支持哪些 key,而这些 key 分别代表什么意思然后再到百度搜索,这样我们能对症下药,正确完美的完成我们的配置文件的配置。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值