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

  1. Correct the datasource id in the annotation/expression to match a configured datasource
  2. Register the missing datasource in the dynamic data source service configuration
  3. Enable fallback-to-default strategy (strategy.isFallbackDefault()) if the default source is acceptable
  4. 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

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)