Update MySQL driver to 8.0, cleanup Hikari usage

This commit is contained in:
Luck 2020-11-10 16:00:36 +00:00
parent 4ce8ea21f9
commit 00d4a2a1da
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
5 changed files with 98 additions and 77 deletions

View File

@ -141,15 +141,15 @@ public enum Dependency {
MARIADB_DRIVER(
"org{}mariadb{}jdbc",
"mariadb-java-client",
"2.6.0",
"fgiCp29Z7X38ULAJNsxZ1wFIVT2u3trSx/VCMxTlA6g=",
"2.7.0",
"ABURDun85Q01kf119r4yjDtl5ju9Fg9uV2nXyU3SEdw=",
Relocation.of("mariadb", "org{}mariadb{}jdbc")
),
MYSQL_DRIVER(
"mysql",
"mysql-connector-java",
"5.1.48",
"VuJsqqOCH1rkr0T5x09mz4uE6gFRatOAPLsOkEm27Kg=",
"8.0.22",
"UBne+9EjFilel6bojyqbB/EYNFpOmCcQu6Iy5JmyL08=",
Relocation.of("mysql", "com{}mysql")
),
POSTGRESQL_DRIVER(

View File

@ -47,37 +47,46 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Abstract {@link ConnectionFactory} using a {@link HikariDataSource}.
*/
public abstract class HikariConnectionFactory implements ConnectionFactory {
protected final StorageCredentials configuration;
private final StorageCredentials configuration;
private HikariDataSource hikari;
public HikariConnectionFactory(StorageCredentials configuration) {
this.configuration = configuration;
}
protected String getDriverClass() {
return null;
}
/**
* Gets the default port used by the database
*
* @return the default port
*/
protected abstract String defaultPort();
protected void appendProperties(HikariConfig config, Map<String, String> properties) {
for (Map.Entry<String, String> property : properties.entrySet()) {
config.addDataSourceProperty(property.getKey(), property.getValue());
}
}
/**
* Configures the {@link HikariConfig} with the relevant database properties.
*
* <p>Each driver does this slightly differently...</p>
*
* @param config the hikari config
* @param address the database address
* @param port the database port
* @param databaseName the database name
* @param username the database username
* @param password the database password
*/
protected abstract void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password);
protected void appendConfigurationInfo(HikariConfig config) {
String address = this.configuration.getAddress();
String[] addressSplit = address.split(":");
address = addressSplit[0];
String port = addressSplit.length > 1 ? addressSplit[1] : "3306";
config.setDataSourceClassName(getDriverClass());
config.addDataSourceProperty("serverName", address);
config.addDataSourceProperty("port", port);
config.addDataSourceProperty("databaseName", this.configuration.getDatabase());
config.setUsername(this.configuration.getUsername());
config.setPassword(this.configuration.getPassword());
/**
* Allows the connection factory instance to override certain properties before they are set.
*
* @param properties the current properties
*/
protected void overrideProperties(Map<String, String> properties) {
// https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery
properties.putIfAbsent("socketTimeout", String.valueOf(TimeUnit.SECONDS.toMillis(30)));
}
@Override
@ -92,17 +101,29 @@ public abstract class HikariConnectionFactory implements ConnectionFactory {
throw e;
}
// set pool name so the logging output can be linked back to us
config.setPoolName("luckperms-hikari");
appendConfigurationInfo(config);
// get the database info/credentials from the config file
String[] addressSplit = this.configuration.getAddress().split(":");
String address = addressSplit[0];
String port = addressSplit.length > 1 ? addressSplit[1] : defaultPort();
// allow the implementation to configure the HikariConfig appropriately with these values
configureDatabase(config, address, port, this.configuration.getDatabase(), this.configuration.getUsername(), this.configuration.getPassword());
// get the extra connection properties from the config
Map<String, String> properties = new HashMap<>(this.configuration.getProperties());
// https://github.com/brettwooldridge/HikariCP/wiki/Rapid-Recovery
properties.putIfAbsent("socketTimeout", String.valueOf(TimeUnit.SECONDS.toMillis(30)));
// allow the implementation to override/make changes to these properties
overrideProperties(properties);
appendProperties(config, properties);
// set the properties
for (Map.Entry<String, String> property : properties.entrySet()) {
config.addDataSourceProperty(property.getKey(), property.getValue());
}
// configure the connection pool
config.setMaximumPoolSize(this.configuration.getMaxPoolSize());
config.setMinimumIdle(this.configuration.getMinIdleConnections());
config.setMaxLifetime(this.configuration.getMaxLifetime());
@ -122,6 +143,20 @@ public abstract class HikariConnectionFactory implements ConnectionFactory {
}
}
@Override
public Connection getConnection() throws SQLException {
if (this.hikari == null) {
throw new SQLException("Unable to get a connection from the pool. (hikari is null)");
}
Connection connection = this.hikari.getConnection();
if (connection == null) {
throw new SQLException("Unable to get a connection from the pool. (getConnection returned null)");
}
return connection;
}
@Override
public Map<Component, Component> getMeta() {
Map<Component, Component> meta = new LinkedHashMap<>();
@ -135,9 +170,9 @@ public abstract class HikariConnectionFactory implements ConnectionFactory {
} catch (SQLException e) {
success = false;
}
long duration = System.currentTimeMillis() - start;
if (success) {
long duration = System.currentTimeMillis() - start;
meta.put(
Component.translatable("luckperms.command.info.storage.meta.ping-key"),
Component.text(duration + "ms", NamedTextColor.GREEN)
@ -151,18 +186,6 @@ public abstract class HikariConnectionFactory implements ConnectionFactory {
return meta;
}
@Override
public Connection getConnection() throws SQLException {
if (this.hikari == null) {
throw new SQLException("Unable to get a connection from the pool. (hikari is null)");
}
Connection connection = this.hikari.getConnection();
if (connection == null) {
throw new SQLException("Unable to get a connection from the pool. (getConnection returned null)");
}
return connection;
}
private static void handleLinkageError(LinkageError linkageError, LuckPermsPlugin plugin) {
List<String> noteworthyClasses = ImmutableList.of(
"org.slf4j.LoggerFactory",

View File

@ -29,9 +29,7 @@ import com.zaxxer.hikari.HikariConfig;
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class MariaDbConnectionFactory extends HikariConnectionFactory {
public MariaDbConnectionFactory(StorageCredentials configuration) {
@ -44,22 +42,20 @@ public class MariaDbConnectionFactory extends HikariConnectionFactory {
}
@Override
protected String getDriverClass() {
return "org.mariadb.jdbc.MariaDbDataSource";
protected String defaultPort() {
return "3306";
}
@Override
protected void appendProperties(HikariConfig config, Map<String, String> properties) {
String propertiesString = properties.entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).collect(Collectors.joining(";"));
// kinda hacky. this will call #setProperties on the datasource, which will append these options
// onto the connections.
config.addDataSourceProperty("properties", propertiesString);
protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) {
config.setDriverClassName("org.mariadb.jdbc.Driver");
config.setJdbcUrl("jdbc:mariadb://" + address + ":" + port + "/" + databaseName);
config.setUsername(username);
config.setPassword(password);
}
@Override
public Function<String, String> getStatementProcessor() {
return s -> s.replace("'", "`"); // use backticks for quotes
}
}

View File

@ -43,12 +43,20 @@ public class MySqlConnectionFactory extends HikariConnectionFactory {
}
@Override
protected String getDriverClass() {
return "com.mysql.jdbc.jdbc2.optional.MysqlDataSource";
protected String defaultPort() {
return "3306";
}
@Override
protected void appendProperties(HikariConfig config, Map<String, String> properties) {
protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) {
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://" + address + ":" + port + "/" + databaseName);
config.setUsername(username);
config.setPassword(password);
}
@Override
protected void overrideProperties(Map<String, String> properties) {
// https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
properties.putIfAbsent("cachePrepStmts", "true");
properties.putIfAbsent("prepStmtCacheSize", "250");
@ -63,13 +71,11 @@ public class MySqlConnectionFactory extends HikariConnectionFactory {
properties.putIfAbsent("alwaysSendSetIsolation", "false");
properties.putIfAbsent("cacheCallableStmts", "true");
// append configurable properties
super.appendProperties(config, properties);
super.overrideProperties(properties);
}
@Override
public Function<String, String> getStatementProcessor() {
return s -> s.replace("'", "`"); // use backticks for quotes
}
}

View File

@ -43,33 +43,29 @@ public class PostgreConnectionFactory extends HikariConnectionFactory {
}
@Override
protected void appendProperties(HikariConfig config, Map<String, String> properties) {
// remove the default config properties which don't exist for PostgreSQL
properties.remove("useUnicode");
properties.remove("characterEncoding");
super.appendProperties(config, properties);
protected String defaultPort() {
return "5432";
}
@Override
protected void appendConfigurationInfo(HikariConfig config) {
String address = this.configuration.getAddress();
String[] addressSplit = address.split(":");
address = addressSplit[0];
String port = addressSplit.length > 1 ? addressSplit[1] : "5432";
String database = this.configuration.getDatabase();
String username = this.configuration.getUsername();
String password = this.configuration.getPassword();
protected void configureDatabase(HikariConfig config, String address, String port, String databaseName, String username, String password) {
config.setDataSourceClassName("org.postgresql.ds.PGSimpleDataSource");
config.addDataSourceProperty("serverName", address);
config.addDataSourceProperty("portNumber", port);
config.addDataSourceProperty("databaseName", database);
config.addDataSourceProperty("databaseName", databaseName);
config.addDataSourceProperty("user", username);
config.addDataSourceProperty("password", password);
}
@Override
protected void overrideProperties(Map<String, String> properties) {
super.overrideProperties(properties);
// remove the default config properties which don't exist for PostgreSQL
properties.remove("useUnicode");
properties.remove("characterEncoding");
}
@Override
public Function<String, String> getStatementProcessor() {
return s -> s.replace("'", "\"");