如何手动创建和配置 MariaDBDataSource

How to create and configure MariaDBDataSource manually

我在使用 MariaDBDataSource 创建未合并的数据源时遇到问题 class。

MariaDbDataSource mysqlDs = new MariaDbDataSource(connectionUrl);
mysqlDs.setPassword(password);
mysqlDs.setUser(username);
return wrapWithPool(mysqlDs);

wrapWithPool 简单地将给定的数据源包装在一个池化数据源(c3p0 池)中。 但是我无法从池中检出连接。每当我这样做时

datasource.getConnection()

我明白了

org.mariadb.jdbc.internal.util.dao.QueryException: Could not connect: Access denied for user 'someuser'@'somehost' (using password: NO)

不知道为什么?我确实设置了非空密码。在 MariaDbDatasource class 上是否还有其他设置以使其使用密码?

编辑: 好的,看来当我不包装 MariaDbDataSource 时一切正常。 所以 c3p0 正在断开连接,从调试中我看到它无法获取密码...... wrap方法很简单

private static DataSource wrapWithPool(DataSource unpooled) throws SQLException {
            unpooled.setLoginTimeout(HOST_REACH_TIMEOUT.getValue());
            Map<String, Object> poolOverrideProps = new HashMap<>();
            poolOverrideProps.put("maxPoolSize", CONNECTION_POOL_SIZE.getValue());
            poolOverrideProps.put("minPoolSize", 1);
            poolOverrideProps.put("checkoutTimeout", HOST_REACH_TIMEOUT.getValue() * 2);
            return DataSources.pooledDataSource(unpooled, poolOverrideProps);

        }

并且它与其他驱动程序(oracle、jtds)一起工作得很好。为什么不使用 mariaDb?

好的,所以我发现了问题。出于某种原因,c3p0 在创建池时将给定的 DataSource class 包装在自己的 WrapperConnectionPoolDataSourceBase class 中。然后它尝试使用反射从中检测身份验证参数。由于MariaDBDataSource没有提供getPassword方法,发现的值为null,因此报错密码未使用

因此,作为解决方法,我做了一个简单的包装器

private static class MariaDbDExtender extends MariaDbDataSource {

        private String password;

        public MariaDbDExtender(String connectionUrl) throws SQLException {
            super(connectionUrl);
        }


        @Override
        public void setPassword(String pass) {
            this.password = pass;
            super.setPassword(pass);
        }

        //this method is required to allow c3p0 magically use reflection to get correct password for connection
        public String getPassword() {
            return password;
        }
    }

以后

MariaDbDExtender mysqlDs = new MariaDbDExtender(connectionUrl);
mysqlDs.setPassword(password);
mysqlDs.setUser(username);
return wrapWithPool(mysqlDs);

它神奇地开始起作用了。这是一些特定于驱动程序的问题,因为 oracle 数据源没有 getPassword 方法,但可以工作。因此,这两个库的一些非常具体的实现细节使其在我的用例中不兼容。