{"record":{"id":"bc6fb4b82e5a4f0a","repo":"jd-opensource/joyagent-jdgenie","slug":"jdbcdialectfactory","errorCode":null,"errorMessage":"JdbcDialectFactory无实现类","messagePattern":"JdbcDialectFactory无实现类","errorType":"exception","errorClass":"JdbcBizException","httpStatus":null,"severity":"error","filePath":"genie-backend/src/main/java/com/jd/genie/data/jdbc/dialect/JdbcDialectLoader.java","lineNumber":23,"sourceCode":"\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.ServiceConfigurationError;\nimport java.util.ServiceLoader;\n\n@Slf4j\npublic final class JdbcDialectLoader {\n\n    private JdbcDialectLoader() {\n    }\n\n\n    public static JdbcDialect load(String url) {\n        ClassLoader cl = Thread.currentThread().getContextClassLoader();\n        List<JdbcDialectFactory> foundFactories = discoverFactories(cl);\n\n        if (foundFactories.isEmpty()) {\n            throw new JdbcBizException(\"JdbcDialectFactory无实现类\");\n        }\n\n        final List<JdbcDialectFactory> matchingFactories =\n                foundFactories.stream().filter(f -> f.acceptsURL(url)).toList();\n\n        if (matchingFactories.isEmpty()) {\n            throw new JdbcBizException(String.format(\"未找到支持%s的JdbcDialectFactory实现类\", url));\n        }\n\n        return matchingFactories.get(0).create();\n    }\n\n    private static List<JdbcDialectFactory> discoverFactories(ClassLoader classLoader) {\n        try {\n            final List<JdbcDialectFactory> result = new LinkedList<>();\n            ServiceLoader.load(JdbcDialectFactory.class, classLoader)\n                    .iterator()\n                    .forEachRemaining(result::add);","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/genie-backend/src/main/java/com/jd/genie/data/jdbc/dialect/JdbcDialectLoader.java#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (pom.xml missing dialect module)\n<dependencies>\n  <dependency>com.jd.genie:genie-data-core</dependency>\n</dependencies>\n// after\n<dependencies>\n  <dependency>com.jd.genie:genie-data-core</dependency>\n  <dependency>com.jd.genie:genie-data-jdbc-mysql</dependency>\n</dependencies>","handlingStrategy":"try-catch","validationCode":"List<JdbcDialectFactory> factories = ServiceLoader.load(JdbcDialectFactory.class,\n    Thread.currentThread().getContextClassLoader()).stream().toList();\nif (factories.isEmpty()) throw new IllegalStateException(\"No JdbcDialectFactory on classpath\");","typeGuard":"boolean hasDialectFactory() {\n    return ServiceLoader.load(JdbcDialectFactory.class,\n        Thread.currentThread().getContextClassLoader()).iterator().hasNext();\n}","tryCatchPattern":"try {\n    JdbcDialect dialect = JdbcDialectLoader.load(url);\n} catch (JdbcBizException e) {\n    log.error(\"No JdbcDialectFactory registered; check dialect dependency and META-INF/services\", e);\n    throw new IllegalStateException(\"Dialect provider missing on classpath\", e);\n}","preventionTips":["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"],"tags":["jdbc","spi","classpath","serviceloader","missing-dependency"],"backgroundTag":"missing-dependency","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}