This is an automated email from the ASF dual-hosted git repository.

jimin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git


The following commit(s) were added to refs/heads/2.x by this push:
     new a18e999b2b bugfix: fix load driver class in Hikari (#7504)
a18e999b2b is described below

commit a18e999b2bc351c3603ec13ae5445ae8c6d6b45c
Author: maple <[email protected]>
AuthorDate: Wed Jul 9 13:39:26 2025 +0800

    bugfix: fix load driver class in Hikari (#7504)
---
 changes/en-us/2.x.md                               |  1 +
 changes/zh-cn/2.x.md                               |  1 +
 .../server/store/HikariDataSourceProvider.java     | 89 +++++++++++++++++++++-
 .../store/db/AbstractDataSourceProviderTest.java   | 81 ++++++++++++++++++++
 4 files changed, 168 insertions(+), 4 deletions(-)

diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index cf0fd5bae3..c2a5e50bef 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -34,6 +34,7 @@ Add changes here for all PR submitted to the 2.x branch.
 - [[#7397](https://github.com/apache/incubator-seata/pull/7397)] Resolve 
NullPointer and port binding errors
 - [[#7502](https://github.com/apache/incubator-seata/pull/7502)] remove extra 
dots and keep the naming style consistent with other tables
 - [[#7498](https://github.com/apache/incubator-seata/pull/7498)] fix the class 
name whitelist check issue in fury deserialization
+- [[#7504](https://github.com/apache/incubator-seata/pull/7504)] fix load 
driver class in Hikari
 
 
 ### optimize:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 4b2cb19ddc..e4d7d15ad3 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -34,6 +34,7 @@
 - [[#7397](https://github.com/apache/incubator-seata/pull/7397)] 解决空指针和端口绑定错误
 - [[#7502](https://github.com/apache/incubator-seata/pull/7502)] 
删除多余点号和保持命名规范统一
 - [[#7498](https://github.com/apache/incubator-seata/pull/7498)] 
修复fury反序列化的类名白名单检查问题
+- [[#7504](https://github.com/apache/incubator-seata/pull/7504)] 修复 Hikari 
中的加载驱动程序类
 
 
 ### optimize:
diff --git 
a/server/src/main/java/org/apache/seata/server/store/HikariDataSourceProvider.java
 
b/server/src/main/java/org/apache/seata/server/store/HikariDataSourceProvider.java
index bb61adeb31..f1390e85d9 100644
--- 
a/server/src/main/java/org/apache/seata/server/store/HikariDataSourceProvider.java
+++ 
b/server/src/main/java/org/apache/seata/server/store/HikariDataSourceProvider.java
@@ -22,8 +22,16 @@ import com.zaxxer.hikari.util.IsolationLevel;
 import org.apache.seata.common.ConfigurationKeys;
 import org.apache.seata.common.loader.LoadLevel;
 import org.apache.seata.core.store.db.AbstractDataSourceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.Properties;
 
 import static 
org.apache.seata.common.DefaultValues.DEFAULT_DB_HIKARI_IDLE_TIMEOUT;
@@ -37,6 +45,8 @@ import static 
org.apache.seata.common.DefaultValues.DEFAULT_DB_HIKARI_VALIDATION
 @LoadLevel(name = "hikari")
 public class HikariDataSourceProvider extends AbstractDataSourceProvider {
 
+    private static final Logger logger = 
LoggerFactory.getLogger(HikariDataSourceProvider.class);
+
     @Override
     public DataSource doGenerate() {
         Properties properties = new Properties();
@@ -52,10 +62,35 @@ public class HikariDataSourceProvider extends 
AbstractDataSourceProvider {
         properties.setProperty("dataSource.maintainTimeStats", "false");
 
         HikariConfig config = new HikariConfig(properties);
-        config.setDriverClassName(getDriverClassName());
-        config.setJdbcUrl(getUrl());
-        config.setUsername(getUser());
-        config.setPassword(getPassword());
+
+        // Get the correct class loader
+        ClassLoader driverClassLoader = getDriverClassLoader();
+        String driverClassName = getDriverClassName();
+
+        // Set driver class name in the correct class loader context
+        ClassLoader originalClassLoader = 
Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(driverClassLoader);
+
+            // 1. Explicitly load and register the driver
+            try {
+                Class<?> driverClass = Class.forName(driverClassName, true, 
driverClassLoader);
+                Driver driver = (Driver) driverClass.newInstance();
+                DriverManager.registerDriver(new DriverWrapper(driver));
+            } catch (Exception e) {
+                logger.warn("Failed to explicitly register driver {}", 
driverClassName, e);
+            }
+
+            // 2. Set configuration
+            config.setDriverClassName(driverClassName);
+            config.setJdbcUrl(getUrl());
+            config.setUsername(getUser());
+            config.setPassword(getPassword());
+
+        } finally {
+            Thread.currentThread().setContextClassLoader(originalClassLoader);
+        }
+
         config.setMaximumPoolSize(getMaxConn());
         config.setMinimumIdle(getMinConn());
         config.setAutoCommit(true);
@@ -78,4 +113,50 @@ public class HikariDataSourceProvider extends 
AbstractDataSourceProvider {
 
         return new HikariDataSource(config);
     }
+
+    /**
+     * Driver wrapper to ensure using the correct class loader
+     */
+    private static class DriverWrapper implements Driver {
+        private final Driver delegate;
+
+        public DriverWrapper(Driver delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public Connection connect(String url, Properties info) throws 
SQLException {
+            return delegate.connect(url, info);
+        }
+
+        @Override
+        public boolean acceptsURL(String url) throws SQLException {
+            return delegate.acceptsURL(url);
+        }
+
+        @Override
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties 
info) throws SQLException {
+            return delegate.getPropertyInfo(url, info);
+        }
+
+        @Override
+        public int getMajorVersion() {
+            return delegate.getMajorVersion();
+        }
+
+        @Override
+        public int getMinorVersion() {
+            return delegate.getMinorVersion();
+        }
+
+        @Override
+        public boolean jdbcCompliant() {
+            return delegate.jdbcCompliant();
+        }
+
+        @Override
+        public java.util.logging.Logger getParentLogger() throws 
SQLFeatureNotSupportedException {
+            return delegate.getParentLogger();
+        }
+    }
 }
diff --git 
a/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java
 
b/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java
index cf8bcae149..7d992cba3d 100644
--- 
a/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java
+++ 
b/server/src/test/java/org/apache/seata/server/store/db/AbstractDataSourceProviderTest.java
@@ -33,6 +33,8 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Import;
 
 import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
 
 /**
  */
@@ -128,4 +130,83 @@ public class AbstractDataSourceProviderTest {
         Class<?> driverClass = Class.forName(mysqlJdbcDriver, true, 
classLoader);
         Assertions.assertNotNull(driverClass);
     }
+
+    @Test
+    @Order(8)
+    public void testHikariDataSourceProviderWithMySQLDriver() {
+        // Set MySQL 8 driver
+        System.setProperty("store.db.driverClassName", mysql8JdbcDriver);
+
+        try {
+            // Use Hikari data source provider
+            DataSource dataSource = 
EnhancedServiceLoader.load(DataSourceProvider.class, hikariDatasourceType)
+                    .provide();
+            Assertions.assertNotNull(dataSource);
+
+            // Verify it's a HikariDataSource type
+            Assertions.assertTrue(dataSource instanceof 
com.zaxxer.hikari.HikariDataSource);
+
+            // The most critical verification: try to get a connection (this 
will trigger the actual driver loading)
+            // Note: This might throw an exception due to database connection 
failure, but importantly, it should not
+            // show "Failed to load driver class" error
+            try {
+                Connection connection = dataSource.getConnection();
+                // If we reach here, it means the driver loaded successfully 
and connection succeeded
+                Assertions.assertNotNull(connection);
+                connection.close();
+            } catch (SQLException e) {
+                // Database connection failure is normal (test environment 
might not have real MySQL), but error message
+                // should not contain driver class loading failure
+                String errorMessage = e.getMessage();
+                Assertions.assertFalse(
+                        errorMessage.contains("Failed to load driver class"),
+                        "Driver class should be loaded successfully, but got: 
" + errorMessage);
+                Assertions.assertFalse(
+                        errorMessage.contains("HikariConfig class loader"),
+                        "Driver classloader issue should be resolved, but got: 
" + errorMessage);
+                // Here we expect connection-related errors, such as 
connection timeout, connection refused, etc.
+                System.out.println("Expected database connection error (driver 
loaded successfully): " + errorMessage);
+            }
+
+        } catch (Exception e) {
+            // If it's a driver loading related exception, the test should fail
+            if (e.getMessage().contains("Failed to load driver class")
+                    || e.getMessage().contains("HikariConfig class loader")) {
+                Assertions.fail("HikariCP should load MySQL driver 
successfully with custom classloader, but got: "
+                        + e.getMessage());
+            }
+            // Other exceptions might be normal (such as configuration issues, 
etc.)
+            System.out.println("Non-driver related exception (might be 
expected): " + e.getMessage());
+        }
+    }
+
+    @Test
+    @Order(9)
+    public void testHikariDataSourceProviderWithMySQLLegacyDriver() {
+        // Test with legacy MySQL driver as well
+        System.setProperty("store.db.driverClassName", mysqlJdbcDriver);
+
+        try {
+            DataSource dataSource = 
EnhancedServiceLoader.load(DataSourceProvider.class, hikariDatasourceType)
+                    .provide();
+            Assertions.assertNotNull(dataSource);
+
+            // Try to get connection to verify driver loading
+            try {
+                Connection connection = dataSource.getConnection();
+                Assertions.assertNotNull(connection);
+                connection.close();
+            } catch (SQLException e) {
+                String errorMessage = e.getMessage();
+                Assertions.assertFalse(
+                        errorMessage.contains("Failed to load driver class"),
+                        "Legacy MySQL driver should also be loaded 
successfully, but got: " + errorMessage);
+            }
+
+        } catch (Exception e) {
+            if (e.getMessage().contains("Failed to load driver class")) {
+                Assertions.fail("HikariCP should load legacy MySQL driver 
successfully, but got: " + e.getMessage());
+            }
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to