报
Failed to configure a DataSource不是数据库连不上,而是启动阶段压根没拿到spring.datasource.url。只要 classpath 上有 JDBC/JPA 依赖,DataSourceAutoConfiguration就会强制装配数据源,找不到url又没有 H2 这类内嵌库,直接拒绝启动。要么把连接属性补齐,要么把自动配置关掉。
Issue & Env(案发现场与环境)
- 业务场景:新建 Spring Boot 项目,pom 里加了
spring-boot-starter-data-jpa(或spring-boot-starter-jdbc),还没写任何数据库连接配置就启动。 - 环境:Spring Boot 2.x / 3.x 均受影响,这是自动配置的设计行为,与具体版本无关。issue #15758 报告用的是 2.0.5.RELEASE,但 3.x 的报错形态一致。
StackTrace(堆栈日志)
启动即挂,控制台报错把两条建议路径都写明了:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be configured by Spring Boot, perhaps you forgot to specify the database connection details?
完整的 Java 异常链:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Failed to determine a suitable driver class
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:652)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:443)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:736)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:339)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:962)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:930)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:596)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1307)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1296)
at com.example.demo.Application.main(Application.java:12)
Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceDriverNotFoundException: Failed to determine a suitable driver class
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:213)
at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:188)
at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:60)
at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.dataSource(DataSourceConfiguration.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:159)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:648)
... 17 more
Reproduce(复现代码)
pom 里引入 JPA starter,不带运行时数据库依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
启动类照常:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.properties 里什么都不写,直接 mvn spring-boot:run,启动就报上面的错误。
Root Cause(根因分析)
Spring Boot 的自动配置是「看依赖下菜」:DataSourceAutoConfiguration 用 @ConditionalOnClass 监听 classpath,一旦发现 DataSource 和 EmbeddedDatabaseType(由 JDBC 驱动或 starter 引入)就在,就认为「这个应用要用数据库」,开始装配 DataSource Bean。
装配时 DataSourceProperties 需要至少一个 spring.datasource.url 来定位数据库;没有 url,它就退而求其次,去 classpath 上找内嵌库(H2、HSQL、Derby)的驱动。两条路都不通时,determineDriverClassName() 抛异常,整个应用上下文拒绝刷新。
所以这个坑的触发条件很明确:JPA/JDBC 依赖在 classpath 上,但既没配 url,也没放内嵌库。issue #15758 的提问者就踩在这——pom 里既有 spring-boot-starter-data-jpa 又有 mysql-connector-java,却忘了写 spring.datasource.*。
The Fix(解决方案)
正解:补上连接属性
给外部数据库补全地址、账号、驱动即可:
spring:
datasource:
url: jdbc:mysql://localhost:3306/my_db
username: user1
password: pass
driver-class-name: com.mysql.cj.jdbc.Driver
用 application.properties 同理:
spring.datasource.url=jdbc:mysql://localhost:3306/my_db
spring.datasource.username=user1
spring.datasource.password=pass
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
测试/演示场景:放一个内嵌库
只想跑起来、不接真库,把 H2 加进 classpath,Spring Boot 会自动用内嵌库配出可用的 DataSource:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
压根不用数据库:关掉自动配置
应用其实不碰关系库(比如只用 Redis、Mongo、ES),是父 POM 里残留了 JPA 依赖,那就别让 DataSourceAutoConfiguration 生效:
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class Application {}
或在配置里指定:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
排除后 Spring Boot 不再装配数据源,应用正常启动。代价是自己保证没有代码去注入 DataSource、JdbcTemplate 或 EntityManager,否则运行时才会报「找不到 Bean」。
