文档章节

怎样排查 Cannot determine embedded database driver class for database type NONE

小致Daddy
 小致Daddy
发布于 03/20 15:59
字数 1162
阅读 68
收藏 0

调试排查 Cannot determine embedded database driver class for database type NONE 的错误
把工程导入IDE里,直接启动应用,抛出来的异常信息是:

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-11-29 14:26:34.478 ERROR 29736 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   :

***************************
APPLICATION FAILED TO START
***************************

Description:

Cannot determine embedded database driver class for database type NONE

Action:

If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).


其实这时有两个思路,直接google搜索Cannot determine embedded database driver class for database type NONE,就可以找到解决办法。

第二种方式,仔细查看日志内容,可以发现有To display the auto-configuration report re-run your application with 'debug' enabled.。

搜索下这个,就可以在spring的官方网站上找到相关的信息:https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html

就是用户只要配置了debug这个开关,就会把auto-configuration 相关的信息打印出来。

熟悉spring的环境变量注入的话,就可以知道有几种打开这个的方式:

在args里增加--debug
在application.properties里增加debug=true
通过-Ddebug=true
增加debug开关之后的信息
增加debug开关之后,可以看到打印出了错误堆栈:

2017-11-29 14:33:08.776 DEBUG 29907 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : Application failed to start due to an exception

org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
    at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:245) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:182) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:42) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
    at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Tomcat.dataSource(DataSourceConfiguration.java:53) ~[spring-boot-autoconfigure-1.4.7.RELEASE.jar:1.4.7.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_112]

抛出异常的代码是:    

/**
     * Determine the driver to use based on this configuration and the environment.
     * @return the driver to use
     * @since 1.4.0
     */
    public String determineDriverClassName() {
        if (StringUtils.hasText(this.driverClassName)) {
            Assert.state(driverClassIsLoadable(),
                    "Cannot load driver class: " + this.driverClassName);
            return this.driverClassName;
        }
        String driverClassName = null;

        if (StringUtils.hasText(this.url)) {
            driverClassName = DatabaseDriver.fromJdbcUrl(this.url).getDriverClassName();
        }

        if (!StringUtils.hasText(driverClassName)) {
            driverClassName = this.embeddedDatabaseConnection.getDriverClassName();
        }

        if (!StringUtils.hasText(driverClassName)) {
            throw new DataSourceBeanCreationException(this.embeddedDatabaseConnection,
                    this.environment, "driver class");
        }
        return driverClassName;
    }


可以看出来是没有找到 DataSource 的driver class,然后抛出了 DataSourceBeanCreationException。

那么一种解决办法是,在maven依赖里加入一些 DataSource driver class。

但是应用自己的代码里并没有使用DataSource,哪里导致spring boot要创建一个DataSource对象?哪里导致spring boot要创建DataSource
从异常栈上,可以找到DataSourceConfiguration$Tomcat 这个类,那么查找下它的引用,可以发现它是被

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration.PooledDataSourceConfiguration import引入的。

    @Configuration
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
            DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
            DataSourceConfiguration.Generic.class })
    protected static class PooledDataSourceConfiguration {

    }


那么 PooledDataSourceConfiguration 是怎么生效的呢?从代码上可以看到@Conditional(PooledDataSourceCondition.class)。

那么再看PooledDataSourceCondition的具体实现:  

 /**
     * {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
     * is set or {@link PooledDataSourceAvailableCondition} applies.
     */
    static class PooledDataSourceCondition extends AnyNestedCondition {

        PooledDataSourceCondition() {
            super(ConfigurationPhase.PARSE_CONFIGURATION);
        }

        @ConditionalOnProperty(prefix = "spring.datasource", name = "type")
        static class ExplicitType {

        }

        @Conditional(PooledDataSourceAvailableCondition.class)
        static class PooledDataSourceAvailable {

        }

    }

 

PooledDataSourceCondition引入了@Conditional(PooledDataSourceAvailableCondition.class) :

    /**
     * {@link Condition} to test if a supported connection pool is available.
     */
    static class PooledDataSourceAvailableCondition extends SpringBootCondition {

        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context,
                AnnotatedTypeMetadata metadata) {
            ConditionMessage.Builder message = ConditionMessage
                    .forCondition("PooledDataSource");
            if (getDataSourceClassLoader(context) != null) {
                return ConditionOutcome
                        .match(message.foundExactly("supported DataSource"));
            }
            return ConditionOutcome
                    .noMatch(message.didNotFind("supported DataSource").atAll());
        }

        /**
         * Returns the class loader for the {@link DataSource} class. Used to ensure that
         * the driver class can actually be loaded by the data source.
         * @param context the condition context
         * @return the class loader
         */
        private ClassLoader getDataSourceClassLoader(ConditionContext context) {
            Class<?> dataSourceClass = new DataSourceBuilder(context.getClassLoader())
                    .findType();
            return (dataSourceClass == null ? null : dataSourceClass.getClassLoader());
        }

    }


从代码里,可以看到是尝试查找dataSourceClass,如果找到,条件就成立。那么debug下,可以发现查找到的dataSourceClass是:org.apache.tomcat.jdbc.pool.DataSource 。

那么再看下org.apache.tomcat.jdbc.pool.DataSource这个类是从哪里来的呢?

从maven依赖树可以看到,依赖是来自:spring-boot-starter-jdbc。所以是应用依赖了spring-boot-starter-jdbc,但是并没有配置DataSource引起的问题。

问题解决办法
有两种:

没有使用到DataSource,则可以把spring-boot-starter-jdbc的依赖去掉,这样就不会触发spring boot相关的代码
把spring boot自动初始化DataSource相关的代码禁止掉
禁止的办法有两种:

在main函数上配置exclude

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })

在application.properties里配置:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration


总结
应用没有使用到DataSource,但是在pom.xml里引入了spring-boot-starter-jdbc
spring-boot-starter-jdbc带入了tomcat-jdbc,它里面有org.apache.tomcat.jdbc.pool.DataSource
spring boot里的PooledDataSourceConfiguration,判断classpath下面有DataSource的实现类,尝试去创建DataSource bean
在初始化DataSourceProperties时,尝试通过jdbc的url来探测driver class
因为应用并没有配置url,所以最终在DataSourceProperties.determineDriverClassName()里抛出Cannot determine embedded database driver class for database type NONE
最后:

排查spring boot的AutoConfiguration问题时,可以按异常栈,一层层排查Configuration是怎么引入的,再排查Condition具体的判断代码。
 

© 著作权归作者所有

小致Daddy

小致Daddy

粉丝 192
博文 577
码字总数 600143
作品 0
济南
技术主管
私信 提问
深入Spring Boot:怎样排查 Cannot determine embedded database driver class for database type NONE

调试排查 Cannot determine embedded database driver class for database type NONE 的错误 把工程导入IDE里,直接启动应用,抛出来的异常信息是: Error starting ApplicationContext. To ...

花漾年华
04/17
15
0
java项目跑不起来,报Cannot determine embedded datasource。。。。

使用了spring boot pom.xml都配置好了 propertys也有数据 datasource 但是 报错 java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Met......

徐一万
2016/10/09
56.2K
3
spring boot 启动报错

spring boot 启动报错:Cannot determine embedded database driver class for database type NONE 解决:application类加注解 @EnableAutoConfiguration(exclude={DataSourceAutoConfigurat......

串串串ding
2018/07/11
55
0
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource c

spring boot启动报错: Description: Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured. Reason: Failed to determin......

wenzhizhon
2018/10/16
1K
0
Docker中运行SpringBoot项目找不到数据源的

如下是我的application.yml配置,本地使用default环境是好使的,但是打包成镜像之后使用docker环境就不好使了: server:port: 12222 mapper:mappers: tk.mybatis.mapper.common.Mapper not-e...

哎码
05/15
244
1

没有更多内容

加载失败,请刷新页面

加载更多

聊聊nacos的LocalConfigInfoProcessor

序 本文主要研究一下nacos的LocalConfigInfoProcessor LocalConfigInfoProcessor nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/impl/LocalConfigInfoProcessor.java p......

go4it
昨天
5
0
前端技术之:webpack热模块替换(HMR)

第一步:安装HMR中间件: npm install --save-dev webpack-hot-middleware 第二步:webpack配置中引入webpack对象 const webpack = require('webpack’); 第三步:增加devServer配置项: ho......

popgis
昨天
5
0
死磕 java线程系列之线程池深入解析——体系结构

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 Java的线程池是块硬骨头,对线程池的源码做深入研究不仅能提高对Java整个并发编程的理解,也能提高自己...

彤哥读源码
昨天
7
0
虚函数表 图解

虚函数表 图解 p504

天王盖地虎626
昨天
6
0
java反射

学习目标  什么是反射  反射运行原理  了解反射机制的相关类  获取 class 对象的 3 种方式  通过反射获取构造方法并使用  通过反射获取成员变量并调用  通过反射获取成员方法并...

流川偑
昨天
5
2

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部