jd-opensource/joyagent-jdgenie · error · JdbcBizException
JdbcDialectFactory无实现类
Error message
JdbcDialectFactory无实现类
What it means
JdbcDialectLoader.load() resolves a JdbcDialect for a JDBC URL via SPI. It first discovers all JdbcDialectFactory implementations through ServiceLoader; if none are found on the classpath it throws this JdbcBizException, meaning no dialect provider is registered at all.
Solutions
- Add the dialect provider dependency (the jar containing JdbcDialectFactory implementations and its META-INF/services/com.jd.genie.data.jdbc.dialect.JdbcDialectFactory file) to the classpath
- Verify the shaded/fat jar includes META-INF/services entries (check with jar tf or unzip -l) and re-enable service-file merging in the shade plugin (ServicesResourceTransformer)
- Ensure the context ClassLoader is set correctly (Thread.currentThread().setContextClassLoader) in plugin/classloader-isolated environments
- Check ServiceLoader registration file exists with the fully-qualified implementation class name
Example fix
// before (pom.xml missing dialect module) <dependencies> <dependency>com.jd.genie:genie-data-core</dependency> </dependencies> // after <dependencies> <dependency>com.jd.genie:genie-data-core</dependency> <dependency>com.jd.genie:genie-data-jdbc-mysql</dependency> </dependencies>
Defensive patterns
Strategy: try-catch
Validate before calling
List<JdbcDialectFactory> factories = ServiceLoader.load(JdbcDialectFactory.class,
Thread.currentThread().getContextClassLoader()).stream().toList();
if (factories.isEmpty()) throw new IllegalStateException("No JdbcDialectFactory on classpath"); Type guard
boolean hasDialectFactory() {
return ServiceLoader.load(JdbcDialectFactory.class,
Thread.currentThread().getContextClassLoader()).iterator().hasNext();
} Try / catch
try {
JdbcDialect dialect = JdbcDialectLoader.load(url);
} catch (JdbcBizException e) {
log.error("No JdbcDialectFactory registered; check dialect dependency and META-INF/services", e);
throw new IllegalStateException("Dialect provider missing on classpath", e);
} Prevention
- Always include a dialect provider jar (with its META-INF/services file) in deployments
- In shaded fat-jars, configure ServicesResourceTransformer so service files are merged
- Check ServiceLoader discovery at startup with a fail-fast health check
- In plugin/classloader environments, set the context ClassLoader before loading
When it happens
Trigger: Calling JdbcDialectLoader.load(url) (directly or via JdbcConnectionFactory/data-source creation) when the classpath contains no JdbcDialectFactory implementation — i.e. no META-INF/services file registering one and no dialect jar dependency.
Common situations: Missing the JDBC/dialect module dependency in the build; shade/plugin fat-jar that strips META-INF/services entries; custom ServiceLoader-unaware classloader (e.g. plugin sandbox) that cannot see the provider; running with a stripped classpath.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Could not find any jdbc dialect factories that implement
- Multiple jdbc dialect factories can handle
- Could not find any jdbc dialect factory that can handled
- Could not load service provider for Catalog factory.
- Failed listing database in catalog
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/bc6fb4b82e5a4f0a.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/data/jdbc/dialect/JdbcDialectLoader.java:23
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
@Slf4j
public final class JdbcDialectLoader {
private JdbcDialectLoader() {
}
public static JdbcDialect load(String url) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
List<JdbcDialectFactory> foundFactories = discoverFactories(cl);
if (foundFactories.isEmpty()) {
throw new JdbcBizException("JdbcDialectFactory无实现类");
}
final List<JdbcDialectFactory> matchingFactories =
foundFactories.stream().filter(f -> f.acceptsURL(url)).toList();
if (matchingFactories.isEmpty()) {
throw new JdbcBizException(String.format("未找到支持%s的JdbcDialectFactory实现类", url));
}
return matchingFactories.get(0).create();
}
private static List<JdbcDialectFactory> discoverFactories(ClassLoader classLoader) {
try {
final List<JdbcDialectFactory> result = new LinkedList<>();
ServiceLoader.load(JdbcDialectFactory.class, classLoader)
.iterator()
.forEachRemaining(result::add);View on GitHub (pinned to 2417e0b8b6)