Skip to content

Commit df6c282

Browse files
authored
GH-80 Refactor database, make postgresql working. (#80)
1 parent 53a0095 commit df6c282

File tree

8 files changed

+121
-129
lines changed

8 files changed

+121
-129
lines changed

eternaleconomy-core/src/main/java/com/eternalcode/economy/EconomyBukkitPlugin.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.eternalcode.economy.account.AccountPaymentService;
1111
import com.eternalcode.economy.account.database.AccountRepository;
1212
import com.eternalcode.economy.account.database.AccountRepositoryImpl;
13-
import com.eternalcode.economy.account.database.AccountRepositoryInMemory;
1413
import com.eternalcode.economy.bridge.BridgeManager;
1514
import com.eternalcode.economy.command.admin.AdminAddCommand;
1615
import com.eternalcode.economy.command.admin.AdminBalanceCommand;
@@ -26,14 +25,14 @@
2625
import com.eternalcode.economy.command.message.InvalidBigDecimalMessage;
2726
import com.eternalcode.economy.command.player.MoneyBalanceCommand;
2827
import com.eternalcode.economy.command.player.MoneyTransferCommand;
28+
import com.eternalcode.economy.database.DatabaseManager;
2929
import com.eternalcode.economy.leaderboard.LeaderboardCommand;
3030
import com.eternalcode.economy.command.validator.notsender.NotSender;
3131
import com.eternalcode.economy.command.validator.notsender.NotSenderValidator;
3232
import com.eternalcode.economy.config.ConfigService;
3333
import com.eternalcode.economy.config.implementation.CommandsConfig;
3434
import com.eternalcode.economy.config.implementation.PluginConfig;
3535
import com.eternalcode.economy.config.implementation.messages.MessageConfig;
36-
import com.eternalcode.economy.database.DatabaseManager;
3736
import com.eternalcode.economy.format.DecimalFormatter;
3837
import com.eternalcode.economy.format.DecimalFormatterImpl;
3938
import com.eternalcode.economy.multification.NoticeBroadcastHandler;
@@ -51,7 +50,6 @@
5150
import java.io.File;
5251
import java.math.BigDecimal;
5352
import java.time.Duration;
54-
import java.util.UUID;
5553
import net.kyori.adventure.platform.AudienceProvider;
5654
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
5755
import net.kyori.adventure.text.minimessage.MiniMessage;

eternaleconomy-core/src/main/java/com/eternalcode/economy/database/AbstractRepositoryOrmLite.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.eternalcode.economy.database;
22

3+
import com.eternalcode.commons.ThrowingFunction;
34
import com.eternalcode.commons.scheduler.Scheduler;
4-
import com.eternalcode.economy.shared.ThrowingFunction;
55
import com.j256.ormlite.dao.Dao;
66
import java.sql.SQLException;
77
import java.util.List;
@@ -52,20 +52,30 @@ protected <T> CompletableFuture<List<T>> selectAll(Class<T> type) {
5252

5353
protected <T, ID, R> CompletableFuture<R> action(
5454
Class<T> type,
55-
ThrowingFunction<Dao<T, ID>, R, SQLException> action) {
56-
CompletableFuture<R> completableFuture = new CompletableFuture<>();
55+
ThrowingFunction<Dao<T, ID>, R, SQLException> action
56+
) {
57+
CompletableFuture<R> future = new CompletableFuture<>();
5758

5859
this.scheduler.runAsync(() -> {
59-
Dao<T, ID> dao = this.databaseManager.getDao(type);
60+
Dao<T, ID> dao;
61+
try {
62+
dao = this.databaseManager.getDao(type);
63+
}
64+
catch (Exception exception) {
65+
future.completeExceptionally(new DatabaseException(
66+
"Failed to get DAO for class: " + type.getName(), exception));
67+
return;
68+
}
6069

6170
try {
62-
completableFuture.complete(action.apply(dao));
71+
future.complete(action.apply(dao));
6372
}
6473
catch (Throwable throwable) {
65-
completableFuture.completeExceptionally(throwable);
74+
future.completeExceptionally(new DatabaseException(
75+
"Database action failed for: " + type.getSimpleName(), throwable));
6676
}
6777
});
6878

69-
return completableFuture;
79+
return future;
7080
}
7181
}

eternaleconomy-core/src/main/java/com/eternalcode/economy/database/DatabaseConfig.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal"})
77
public class DatabaseConfig extends OkaeriConfig implements DatabaseSettings {
88

9-
@Comment({"Type of the database driver (e.g., SQLITE, H2, MY_SQL, MARIA_DB, POSTGRE_SQL).", "Determines the "
9+
@Comment({"Type of the database driver (e.g., SQLITE, H2, MYSQL, MARIADB, POSTGRESQL).", "Determines the "
1010
+ "database type "
1111
+ "to be used."})
12-
public DatabaseDriverType driverType = DatabaseDriverType.SQLITE;
12+
public DatabaseDriverType databaseType = DatabaseDriverType.SQLITE;
1313

1414
@Comment({"Hostname of the database server.", "For local databases, this is usually 'localhost'."})
1515
public String hostname = "localhost";
@@ -40,37 +40,37 @@ public class DatabaseConfig extends OkaeriConfig implements DatabaseSettings {
4040
public int timeout = 30000;
4141

4242
@Override
43-
public DatabaseDriverType getDriverType() {
44-
return this.driverType;
43+
public DatabaseDriverType databaseType() {
44+
return this.databaseType;
4545
}
4646

4747
@Override
48-
public String getHostname() {
48+
public String hostname() {
4949
return this.hostname;
5050
}
5151

5252
@Override
53-
public int getPort() {
53+
public int port() {
5454
return this.port;
5555
}
5656

5757
@Override
58-
public String getDatabase() {
58+
public String database() {
5959
return this.database;
6060
}
6161

6262
@Override
63-
public String getUsername() {
63+
public String username() {
6464
return this.username;
6565
}
6666

6767
@Override
68-
public String getPassword() {
68+
public String password() {
6969
return this.password;
7070
}
7171

7272
@Override
73-
public boolean isSSL() {
73+
public boolean ssl() {
7474
return this.ssl;
7575
}
7676

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
package com.eternalcode.economy.database;
22

3-
class DatabaseConnectionDriverConstant {
3+
final class DatabaseConnectionDriverConstant {
4+
5+
private DatabaseConnectionDriverConstant() {}
46

57
// mysql
68
static final String MYSQL_DRIVER = "com.mysql.cj.jdbc.Driver";
7-
static final String MYSQL_JDBC_URL = "jdbc:mysql://%s:%s/%s?useSSL=%s&requireSSL=%s";
9+
static final String MYSQL_JDBC_URL = "jdbc:mysql://%s:%s/%s?sslMode=%s";
810

9-
// maria db
11+
// mariadb — accepts "true"/"false" as valid sslMode values (aliases for "verify-full" and "disable")
1012
static final String MARIADB_DRIVER = "org.mariadb.jdbc.Driver";
11-
static final String MARIADB_JDBC_URL = "jdbc:mariadb://%s:%s/%s?useSSL=%s&requireSSL=%s";
13+
static final String MARIADB_JDBC_URL = "jdbc:mariadb://%s:%s/%s?sslMode=%s";
1214

1315
// h2
1416
static final String H2_DRIVER = "org.h2.Driver";
@@ -20,5 +22,13 @@ class DatabaseConnectionDriverConstant {
2022

2123
// postgresql
2224
static final String POSTGRESQL_DRIVER = "org.postgresql.Driver";
23-
static final String POSTGRESQL_JDBC_URL = "jdbc:postgresql://%s:%s/?ssl=%s";
25+
static final String POSTGRESQL_JDBC_URL = "jdbc:postgresql://%s:%s/%s?sslmode=%s";
26+
27+
static String sslParamForMySQL(boolean enabled) {
28+
return enabled ? "REQUIRED" : "DISABLED";
29+
}
30+
31+
static String sslParamForPostgreSQL(boolean enabled) {
32+
return enabled ? "require" : "disable";
33+
}
2434
}
Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
package com.eternalcode.economy.database;
22

3+
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.*;
4+
35
public enum DatabaseDriverType {
46

5-
MY_SQL,
6-
MARIA_DB,
7-
POSTGRE_SQL,
8-
H2,
9-
SQLITE
7+
MYSQL(MYSQL_DRIVER, MYSQL_JDBC_URL),
8+
MARIADB(MARIADB_DRIVER, MARIADB_JDBC_URL),
9+
POSTGRESQL(POSTGRESQL_DRIVER, POSTGRESQL_JDBC_URL),
10+
H2(H2_DRIVER, H2_JDBC_URL),
11+
SQLITE(SQLITE_DRIVER, SQLITE_JDBC_URL);
12+
13+
private final String driver;
14+
private final String urlFormat;
15+
16+
DatabaseDriverType(String driver, String urlFormat) {
17+
this.driver = driver;
18+
this.urlFormat = urlFormat;
19+
}
20+
21+
public String getDriver() {
22+
return driver;
23+
}
24+
25+
public String formatUrl(Object... args) {
26+
return String.format(urlFormat, args);
27+
}
1028
}

eternaleconomy-core/src/main/java/com/eternalcode/economy/database/DatabaseException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ public DatabaseException(String message) {
88
public DatabaseException(String message, Throwable cause) {
99
super(message, cause);
1010
}
11-
}
11+
}

eternaleconomy-core/src/main/java/com/eternalcode/economy/database/DatabaseManager.java

Lines changed: 47 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
package com.eternalcode.economy.database;
22

3-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.H2_DRIVER;
4-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.H2_JDBC_URL;
5-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.MARIADB_DRIVER;
6-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.MARIADB_JDBC_URL;
7-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.MYSQL_DRIVER;
8-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.MYSQL_JDBC_URL;
9-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.POSTGRESQL_DRIVER;
10-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.POSTGRESQL_JDBC_URL;
11-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.SQLITE_DRIVER;
12-
import static com.eternalcode.economy.database.DatabaseConnectionDriverConstant.SQLITE_JDBC_URL;
13-
143
import com.google.common.base.Stopwatch;
154
import com.j256.ormlite.dao.Dao;
165
import com.j256.ormlite.dao.DaoManager;
@@ -28,94 +17,65 @@ public class DatabaseManager {
2817

2918
private final Logger logger;
3019
private final File dataFolder;
31-
private final DatabaseSettings databaseSettings;
20+
private final DatabaseSettings settings;
3221
private final Map<Class<?>, Dao<?, ?>> cachedDao = new ConcurrentHashMap<>();
3322
private HikariDataSource dataSource;
3423
private ConnectionSource connectionSource;
3524

36-
public DatabaseManager(Logger logger, File dataFolder, DatabaseSettings databaseSettings) {
25+
public DatabaseManager(Logger logger, File dataFolder, DatabaseSettings settings) {
3726
this.logger = logger;
3827
this.dataFolder = dataFolder;
39-
this.databaseSettings = databaseSettings;
28+
this.settings = settings;
4029
}
4130

4231
public void connect() {
4332
try {
4433
Stopwatch stopwatch = Stopwatch.createStarted();
4534

4635
this.dataSource = new HikariDataSource();
47-
48-
DatabaseSettings settings = this.databaseSettings;
49-
5036
this.dataSource.addDataSourceProperty("cachePrepStmts", "true");
5137
this.dataSource.addDataSourceProperty("prepStmtCacheSize", "250");
5238
this.dataSource.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
5339
this.dataSource.addDataSourceProperty("useServerPrepStmts", "true");
5440

5541
this.dataSource.setMaximumPoolSize(settings.poolSize());
5642
this.dataSource.setConnectionTimeout(settings.timeout());
57-
this.dataSource.setUsername(settings.getUsername());
58-
this.dataSource.setPassword(settings.getPassword());
59-
60-
DatabaseDriverType driverType = settings.getDriverType();
61-
switch (driverType) {
62-
case MY_SQL -> {
63-
this.dataSource.setDriverClassName(MYSQL_DRIVER);
64-
this.dataSource.setJdbcUrl(String.format(
65-
MYSQL_JDBC_URL,
66-
settings.getHostname(),
67-
settings.getPort(),
68-
settings.getDatabase(),
69-
this.databaseSettings.isSSL(),
70-
this.databaseSettings.isSSL())
71-
);
72-
}
73-
74-
case MARIA_DB -> {
75-
this.dataSource.setDriverClassName(MARIADB_DRIVER);
76-
this.dataSource.setJdbcUrl(String.format(
77-
MARIADB_JDBC_URL,
78-
settings.getHostname(),
79-
settings.getPort(),
80-
settings.getDatabase(),
81-
this.databaseSettings.isSSL(),
82-
this.databaseSettings.isSSL())
83-
);
84-
}
85-
86-
case H2 -> {
87-
this.dataSource.setDriverClassName(H2_DRIVER);
88-
this.dataSource.setJdbcUrl(String.format(
89-
H2_JDBC_URL,
90-
this.dataFolder)
91-
);
92-
}
93-
94-
case SQLITE -> {
95-
this.dataSource.setDriverClassName(SQLITE_DRIVER);
96-
this.dataSource.setJdbcUrl(String.format(
97-
SQLITE_JDBC_URL,
98-
this.dataFolder)
99-
);
100-
}
101-
102-
case POSTGRE_SQL -> {
103-
this.dataSource.setDriverClassName(POSTGRESQL_DRIVER);
104-
this.dataSource.setJdbcUrl(String.format(
105-
POSTGRESQL_JDBC_URL,
106-
settings.getHostname(), settings.getPort(), this.databaseSettings.isSSL())
107-
);
108-
}
109-
110-
default -> throw new DatabaseException("SQL type '" + driverType + "' not found");
111-
}
112-
113-
this.connectionSource = new DataSourceConnectionSource(this.dataSource, this.dataSource.getJdbcUrl());
114-
this.logger.info("Loaded database " + driverType + " in " +
115-
stopwatch.elapsed(TimeUnit.MILLISECONDS) + "ms");
43+
this.dataSource.setUsername(settings.username());
44+
this.dataSource.setPassword(settings.password());
45+
46+
DatabaseDriverType type = settings.databaseType();
47+
this.dataSource.setDriverClassName(type.getDriver());
48+
49+
String jdbcUrl = switch (type) {
50+
case H2, SQLITE -> type.formatUrl(dataFolder);
51+
case POSTGRESQL -> type.formatUrl(
52+
settings.hostname(),
53+
settings.port(),
54+
settings.database(),
55+
DatabaseConnectionDriverConstant.sslParamForPostgreSQL(settings.ssl())
56+
);
57+
case MYSQL -> type.formatUrl(
58+
settings.hostname(),
59+
settings.port(),
60+
settings.database(),
61+
DatabaseConnectionDriverConstant.sslParamForMySQL(settings.ssl())
62+
);
63+
case MARIADB -> type.formatUrl(
64+
settings.hostname(),
65+
settings.port(),
66+
settings.database(),
67+
String.valueOf(settings.ssl())
68+
);
69+
};
70+
71+
this.dataSource.setJdbcUrl(jdbcUrl);
72+
73+
this.connectionSource = new DataSourceConnectionSource(this.dataSource, jdbcUrl);
74+
75+
this.logger.info("Loaded database " + type + " in " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + "ms");
11676
}
117-
catch (DatabaseException | SQLException exception) {
118-
throw new RuntimeException("Failed to connect to the database", exception);
77+
catch (Exception exception) {
78+
throw new DatabaseException("Failed to connect to the database", exception);
11979
}
12080
}
12181

@@ -131,19 +91,15 @@ public void close() {
13191

13292
@SuppressWarnings("unchecked")
13393
public <T, ID> Dao<T, ID> getDao(Class<T> type) {
134-
try {
135-
Dao<?, ?> dao = this.cachedDao.get(type);
136-
137-
if (dao == null) {
138-
dao = DaoManager.createDao(this.connectionSource, type);
139-
this.cachedDao.put(type, dao);
140-
}
141-
142-
return (Dao<T, ID>) dao;
143-
}
144-
catch (SQLException exception) {
145-
throw new RuntimeException(exception);
146-
}
94+
return (Dao<T, ID>) this.cachedDao.computeIfAbsent(
95+
type, clazz -> {
96+
try {
97+
return DaoManager.createDao(this.connectionSource, clazz);
98+
}
99+
catch (SQLException exception) {
100+
throw new DatabaseException("Failed to create DAO for " + clazz.getName(), exception);
101+
}
102+
});
147103
}
148104

149105
public ConnectionSource connectionSource() {

0 commit comments

Comments
 (0)