我在使用MariaDBDataSource类创建非池化数据源时遇到问题。
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类上设置以使其使用密码吗?
编辑: 好的,所以看来当我不包装MariaDbDataSource时一切正常。 所以c3p0打破了连接,从调试我发现它无法获得密码...... 包装方法非常简单
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?
答案 0 :(得分:0)
好的,所以我发现了这个问题。出于某种原因,创建池时c3p0将给定的DataSource类包装在自己的WrapperConnectionPoolDataSourceBase类中。然后它尝试使用反射从中检测身份验证参数。由于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方法,但有效。因此,这两个库的一些非常具体的实现细节只会使它在我的用例中不兼容。