mybatis/mybatis-3 · critical · SQLException

Error setting driver on UnpooledDataSource.

Error message

Error setting driver on UnpooledDataSource.

What it means

UnpooledDataSource calms driver initialization into a memoized block: it loads the class named by the 'driver' property (via the driverClassLoader if set), instantiates it, registers a DriverProxy, and returns the instance. Any failure (ClassNotFoundException, instantiation error, security exception, registerDriver failure) is wrapped in RuntimeException, then rethrown as SQLException 'Error setting driver on UnpooledDataSource.' with the original cause attached. The actual reason is in the cause chain.

Source

Thrown at src/main/java/org/apache/ibatis/datasource/unpooled/UnpooledDataSource.java:251

  private void initializeDriver() throws SQLException {
    try {
      registeredDrivers.computeIfAbsent(driver, x -> {
        Class<?> driverType;
        try {
          if (driverClassLoader != null) {
            driverType = Class.forName(x, true, driverClassLoader);
          } else {
            driverType = Resources.classForName(x);
          }
          Driver driverInstance = (Driver) driverType.getDeclaredConstructor().newInstance();
          DriverManager.registerDriver(new DriverProxy(driverInstance));
          return driverInstance;
        } catch (Exception e) {
          throw new RuntimeException("Error setting driver on UnpooledDataSource.", e);
        }
      });
    } catch (RuntimeException re) {
      throw new SQLException("Error setting driver on UnpooledDataSource.", re.getCause());
    }
  }

  private void configureConnection(Connection conn) throws SQLException {
    if (defaultNetworkTimeout != null) {
      conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
    }
    if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
      conn.setAutoCommit(autoCommit);
    }
    if (defaultTransactionIsolationLevel != null) {
      conn.setTransactionIsolation(defaultTransactionIsolationLevel);
    }
  }

  private static class DriverProxy implements Driver {
    private final Driver driver;

View on GitHub (pinned to 008069adb1)

Solutions

  1. Inspect getCause() of the SQLException: ClassNotFoundException names the exact missing/typo'd class
  2. Add or fix the JDBC driver dependency and use the correct current class name (e.g., com.mysql.cj.jdbc.Driver for Connector/J 8+)
  3. Verify with Class.forName("your.Driver") in the same runtime/classloader that runs MyBatis
  4. In classloader-restricted environments, supply a driverClassLoader via UnpooledDataSource.setDriverClassLoader (e.g., thread context classloader)
  5. On JDBC 4+ drivers you may omit the driver property entirely — DriverManager auto-discovers drivers via META-INF/services

Example fix

<!-- before -->
<property name="driver" value="com.mysql.jdbc.Driver"/> <!-- removed in Connector/J 8 -->

<!-- after -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<!-- or omit 'driver' entirely on JDBC4+ -->
Defensive patterns

Strategy: validation

Validate before calling

// Verify the driver class loads in the runtime classloader before building the config:
String driver = "com.mysql.cj.jdbc.Driver";
Class.forName(driver, true, Thread.currentThread().getContextClassLoader());

Try / catch

try {
  dataSource.getConnection();
} catch (SQLException e) {
  if ("Error setting driver on UnpooledDataSource.".equals(e.getMessage())) {
    Throwable c = e.getCause(); // ClassNotFoundException etc. names the problem
    throw new IllegalStateException("JDBC driver misconfigured: " + c, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Setting <property name="driver" value="..."/> to a class name not on the classpath (typo, missing JDBC driver jar, wrong artifact for DB version); driver class present but lacking a public no-arg constructor; classloader isolation (driver jar in a child classloader, e.g., some app servers/plugins) with no driverClassLoader configured; SecurityManager blocking instantiation or registration.

Common situations: Missing JDBC driver dependency (e.g., forgot mysql-connector-j or postgresql in pom.xml); upgrading a DB and driver class rename (e.g., com.mysql.jdbc.Driver -> com.mysql.cj.jdbc.Driver); shading/relocating the driver class; running in OSGi or complex classloader layouts.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/09cc4ebffe3db320. Report an issue: GitHub.