-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
DriverDataSource has several load methods which load in the order:
- load from registered drivers in DriverManager
- load from ContextClassLoader
- load from DriverDataSource's classloader
- load by connection url from DriverManager
the 4th load method is the same with the 1st essentially.
Suppose we have two conflict JDBC Drivers(they have the same class name but different implementations), we normally prefer the 2nd load method by ContextClassLoader to load the expected one. But if DriverManager already load the conflicted one, as the 1st load method's priority is higher than the 2nd, we would never have the opportunity to load the exected Driver.
A real example of conflicted drivers is org.opengauss:opengauss-jdbc and org.postgresql:postgresql, the coresponding codes are:
<!-- pom.xml -->
<dependencies>
<dependency>
<groupId>org.opengauss</groupId>
<artifactId>opengauss-jdbc</artifactId>
<version>5.1.0</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>6.3.0</version>
</dependency>
</dependencies>// Demo.java
Class.forName("org.postgresql.Driver");
URL url = new URL("https://repo1.maven.org/maven2/org/postgresql/postgresql/42.7.6/postgresql-42.7.6.jar");
URLClassLoader loader = new ChildFirstClassLoader(new URL[] {url}, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(loader);
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres");
config.setUsername("postgres");
config.setPassword("");
config.setDriverClassName("org.postgresql.Driver");
HikariDataSource datasource = new HikariDataSource(config);
try (Connection connection = datasource.getConnection()) {
System.out.println("connection = " + connection);
}
datasource.close();The Demo.java will load opengauss's Driver although we declared a ChildFirstClassLoader.
the solution maybe remove the 1st load method.