hs-web/hsweb-framework · error · DataSourceNotFoundException
数据源[ ]不存在
Error message
数据源[${id}]不存在 What it means
The AOP data-source switcher intercepts a method annotated with @UseDataSource (or similar), resolves the datasource id (possibly via SpEL), and throws DataSourceNotFoundException when DataSourceHolder.existing(id) reports no such datasource and fallback-to-default is disabled.
Solutions
- Correct the datasource id in the annotation/expression to match a configured datasource
- Register the missing datasource in the dynamic data source service configuration
- Enable fallback-to-default strategy (strategy.isFallbackDefault()) if the default source is acceptable
- Log available datasource ids and compare with the requested id
Example fix
// before
@UseDataSource("mysql_biz")
public List<Order> listOrders() {...}
// after
@UseDataSource("mysql_business")
public List<Order> listOrders() {...} Defensive patterns
Strategy: validation
Validate before calling
if (!DataSourceHolder.existing("mysql_business")) {
throw new IllegalStateException("datasource mysql_business not registered");
} Type guard
static boolean hasDataSource(String id) {
return DataSourceHolder.isDynamicDataSourceReady() && DataSourceHolder.existing(id);
} Try / catch
try {
return method();
} catch (DataSourceNotFoundException e) {
log.error("datasource missing: {}", e.getMessage());
DataSourceHolder.switcher().datasource().useDefault();
return method();
} Prevention
- Verify @UseDataSource ids against configured datasources at startup
- Enable fallback-to-default for non-critical paths
- Test SpEL id expressions with real arguments
- Keep datasource registry and annotations in sync via a startup checker
When it happens
Trigger: Annotating a service method with a datasource id string that no registered dynamic datasource provides, or an id expression (SpEL on method args) evaluating to a nonexistent datasource.
Common situations: Typo in @UseDataSource value; datasource not added to the dynamicDataSourceService configuration; renamed database after config change; SpEL expression pointing at an argument value that has no matching datasource.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
AI-assisted analysis of hs-web/hsweb-framework@b2cfc85a57 (2026-09-13).
Data as JSON: /api/errors/b9ca9fc9e7a1e87a.
Report an issue: GitHub.
Appendix: source
Thrown at hsweb-datasource/hsweb-datasource-api/src/main/java/org/hswebframework/web/datasource/AopDataSourceSwitcherAutoConfiguration.java:127
if (strategy == null) {
dataSourceChanged.set(false);
logger.warn("strategy matcher found:{}, but strategy is null!", matcher);
} else {
logger.debug("switch datasource. use strategy:{}", strategy);
if (strategy.isUseDefaultDataSource()) {
DataSourceHolder.switcher().datasource().useDefault();
} else {
try {
String id = strategy.getDataSourceId();
if (StringUtils.hasText(id)) {
if (id.contains("${")) {
id = ExpressionUtils.analytical(id, context.getNamedArguments(), "spel");
}
if (!DataSourceHolder.existing(id)) {
if (strategy.isFallbackDefault()) {
DataSourceHolder.switcher().datasource().useDefault();
} else {
throw new DataSourceNotFoundException("数据源[" + id + "]不存在");
}
} else {
DataSourceHolder.switcher().datasource().use(id);
}
dataSourceChanged.set(true);
}
} catch (RuntimeException e) {
dataSourceChanged.set(false);
throw e;
} catch (Exception e) {
dataSourceChanged.set(false);
throw new RuntimeException(e.getMessage(), e);
}
}
if (StringUtils.hasText(strategy.getDatabase())) {
databaseChanged.set(true);
DataSourceHolder.switcher().datasource().use(strategy.getDatabase());
}View on GitHub (pinned to b2cfc85a57)