mirror of
https://github.com/plexusorg/Plex.git
synced 2026-06-04 05:26:55 +00:00
ORMLite to JDBI
This commit is contained in:
@@ -4,7 +4,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnlyApi("com.j256.ormlite:ormlite-core:6.1")
|
compileOnlyApi("org.jdbi:jdbi3-core:3.53.0")
|
||||||
api("com.google.code.gson:gson:2.13.2")
|
api("com.google.code.gson:gson:2.13.2")
|
||||||
|
|
||||||
compileOnly("io.papermc.paper:paper-api:26.1.2.build.+")
|
compileOnly("io.papermc.paper:paper-api:26.1.2.build.+")
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package dev.plex.api.storage;
|
|
||||||
|
|
||||||
import com.j256.ormlite.dao.Dao;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates ORMLite DAOs for module-scoped tables.
|
|
||||||
*/
|
|
||||||
public interface ModuleOrm
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Creates or returns a cached DAO for a module-local table.
|
|
||||||
*
|
|
||||||
* @param entityClass ORMLite entity class
|
|
||||||
* @param localTableName module-local table name
|
|
||||||
* @param <T> entity type
|
|
||||||
* @param <ID> entity ID type
|
|
||||||
* @return ORMLite DAO using the module-prefixed physical table
|
|
||||||
* @throws SQLException if the DAO cannot be created
|
|
||||||
*/
|
|
||||||
<T, ID> Dao<T, ID> dao(Class<T> entityClass, String localTableName) throws SQLException;
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package dev.plex.api.storage;
|
package dev.plex.api.storage;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module-scoped storage namespace.
|
* Module-scoped storage namespace.
|
||||||
@@ -30,19 +30,10 @@ public interface ModuleStorage
|
|||||||
ModuleMigrations migrations();
|
ModuleMigrations migrations();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns module ORMLite DAO operations.
|
* Returns the shared JDBI instance. Build SQL with {@link #table(String)} for
|
||||||
|
* physical-table resolution; use {@code jdbi().inTransaction(...)} for multi-statement transactions.
|
||||||
*
|
*
|
||||||
* @return module ORMLite DAO operations
|
* @return shared JDBI instance
|
||||||
*/
|
*/
|
||||||
ModuleOrm orm();
|
Jdbi jdbi();
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs work inside a storage transaction.
|
|
||||||
*
|
|
||||||
* @param callable work to run
|
|
||||||
* @param <T> callback result type
|
|
||||||
* @return callback result
|
|
||||||
* @throws SQLException if the transaction cannot complete
|
|
||||||
*/
|
|
||||||
<T> T transaction(SqlCallable<T> callable) throws SQLException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package dev.plex.api.storage;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback used for SQL work that does not receive a connection directly.
|
|
||||||
*
|
|
||||||
* @param <T> callback result type
|
|
||||||
*/
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface SqlCallable<T>
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Runs SQL work.
|
|
||||||
*
|
|
||||||
* @return callback result
|
|
||||||
* @throws SQLException if the SQL work cannot complete
|
|
||||||
*/
|
|
||||||
T call() throws SQLException;
|
|
||||||
}
|
|
||||||
@@ -28,8 +28,7 @@ dependencies {
|
|||||||
library("org.postgresql:postgresql:42.7.11")
|
library("org.postgresql:postgresql:42.7.11")
|
||||||
library("org.xerial:sqlite-jdbc:3.53.1.0")
|
library("org.xerial:sqlite-jdbc:3.53.1.0")
|
||||||
library("com.zaxxer:HikariCP:7.0.2")
|
library("com.zaxxer:HikariCP:7.0.2")
|
||||||
library("com.j256.ormlite:ormlite-core:6.1")
|
library("org.jdbi:jdbi3-core:3.53.0")
|
||||||
library("com.j256.ormlite:ormlite-jdbc:6.1")
|
|
||||||
library("org.jetbrains:annotations:26.1.0")
|
library("org.jetbrains:annotations:26.1.0")
|
||||||
compileOnly("io.papermc.paper:paper-api:${paperApiVersion}.build.+")
|
compileOnly("io.papermc.paper:paper-api:${paperApiVersion}.build.+")
|
||||||
compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") {
|
compileOnly("com.github.MilkBowl:VaultAPI:1.7.1") {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import dev.plex.player.PlexPlayer;
|
|||||||
import dev.plex.punishment.PunishmentManager;
|
import dev.plex.punishment.PunishmentManager;
|
||||||
import dev.plex.services.ServiceManager;
|
import dev.plex.services.ServiceManager;
|
||||||
import dev.plex.storage.RedisConnection;
|
import dev.plex.storage.RedisConnection;
|
||||||
import dev.plex.storage.SQLConnection;
|
|
||||||
import dev.plex.storage.StorageType;
|
import dev.plex.storage.StorageType;
|
||||||
|
import dev.plex.storage.database.Database;
|
||||||
import dev.plex.storage.player.SQLPlayerData;
|
import dev.plex.storage.player.SQLPlayerData;
|
||||||
import dev.plex.storage.player.PlayerModuleDataRepository;
|
import dev.plex.storage.player.PlayerModuleDataRepository;
|
||||||
import dev.plex.storage.player.SQLPlayerModuleData;
|
import dev.plex.storage.player.SQLPlayerModuleData;
|
||||||
@@ -63,7 +63,7 @@ public class Plex extends JavaPlugin
|
|||||||
public Config toggles;
|
public Config toggles;
|
||||||
public File modulesFolder;
|
public File modulesFolder;
|
||||||
private StorageType storageType = StorageType.SQLITE;
|
private StorageType storageType = StorageType.SQLITE;
|
||||||
private SQLConnection sqlConnection;
|
private Database database;
|
||||||
private RedisConnection redisConnection;
|
private RedisConnection redisConnection;
|
||||||
|
|
||||||
private PlayerCache playerCache;
|
private PlayerCache playerCache;
|
||||||
@@ -146,7 +146,7 @@ public class Plex extends JavaPlugin
|
|||||||
// Don't add default entries to these files
|
// Don't add default entries to these files
|
||||||
indefBans.load(false);
|
indefBans.load(false);
|
||||||
|
|
||||||
sqlConnection = new SQLConnection(this);
|
database = new Database(this);
|
||||||
redisConnection = new RedisConnection(this);
|
redisConnection = new RedisConnection(this);
|
||||||
|
|
||||||
playerCache = new PlayerCache();
|
playerCache = new PlayerCache();
|
||||||
@@ -220,10 +220,10 @@ public class Plex extends JavaPlugin
|
|||||||
PlexLog.log("Redis is disabled in the configuration file, not connecting.");
|
PlexLog.log("Redis is disabled in the configuration file, not connecting.");
|
||||||
}
|
}
|
||||||
|
|
||||||
punishmentRepository = new SQLPunishment(sqlConnection.getConnectionSource(), api.scheduler().asyncExecutor());
|
punishmentRepository = new SQLPunishment(database.getJdbi(), api.scheduler().asyncExecutor());
|
||||||
playerRepository = new SQLPlayerData(sqlConnection.getConnectionSource(), punishmentRepository);
|
playerRepository = new SQLPlayerData(database.getJdbi(), punishmentRepository, storageType);
|
||||||
playerModuleDataRepository = new SQLPlayerModuleData(sqlConnection, storageType);
|
playerModuleDataRepository = new SQLPlayerModuleData(database.getJdbi(), storageType);
|
||||||
noteRepository = new SQLNotes(sqlConnection.getConnectionSource(), api.scheduler().asyncExecutor());
|
noteRepository = new SQLNotes(database.getJdbi(), api.scheduler().asyncExecutor());
|
||||||
playerService = new PlayerService(playerCache, playerRepository);
|
playerService = new PlayerService(playerCache, playerRepository);
|
||||||
playerNameResolver = new PlayerNameResolver(playerService);
|
playerNameResolver = new PlayerNameResolver(playerService);
|
||||||
|
|
||||||
@@ -275,9 +275,9 @@ public class Plex extends JavaPlugin
|
|||||||
|
|
||||||
moduleManager.disableModules();
|
moduleManager.disableModules();
|
||||||
|
|
||||||
if (sqlConnection != null)
|
if (database != null)
|
||||||
{
|
{
|
||||||
sqlConnection.close();
|
database.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ final class DefaultStorageApi implements StorageApi
|
|||||||
@Override
|
@Override
|
||||||
public <T> T withConnection(SqlFunction<T> function) throws SQLException
|
public <T> T withConnection(SqlFunction<T> function) throws SQLException
|
||||||
{
|
{
|
||||||
try (Connection connection = plugin.getSqlConnection().getCon())
|
try (Connection connection = plugin.getDatabase().getConnection())
|
||||||
{
|
{
|
||||||
return function.apply(connection);
|
return function.apply(connection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package dev.plex.storage;
|
|
||||||
|
|
||||||
import dev.plex.Plex;
|
|
||||||
import dev.plex.storage.database.Database;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database bootstrap and connection holder.
|
|
||||||
*
|
|
||||||
* <p>The historical name is kept so existing module-facing accessors do not break.</p>
|
|
||||||
*/
|
|
||||||
public class SQLConnection extends Database
|
|
||||||
{
|
|
||||||
public SQLConnection(Plex plugin)
|
|
||||||
{
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.sql.Connection getCon() throws java.sql.SQLException
|
|
||||||
{
|
|
||||||
return getConnection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -134,6 +134,33 @@ public enum StorageType
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String playerUpsertSql()
|
||||||
|
{
|
||||||
|
return switch (this)
|
||||||
|
{
|
||||||
|
case SQLITE, POSTGRES -> """
|
||||||
|
INSERT INTO players (uuid, last_known_name, login_msg, prefix, staffChat, commandspy)
|
||||||
|
VALUES (:uuid, :name, :login, :prefix, :staffChat, :commandSpy)
|
||||||
|
ON CONFLICT(uuid) DO UPDATE SET
|
||||||
|
last_known_name = excluded.last_known_name,
|
||||||
|
login_msg = excluded.login_msg,
|
||||||
|
prefix = excluded.prefix,
|
||||||
|
staffChat = excluded.staffChat,
|
||||||
|
commandspy = excluded.commandspy
|
||||||
|
""";
|
||||||
|
case MARIADB -> """
|
||||||
|
INSERT INTO `players` (`uuid`, `last_known_name`, `login_msg`, `prefix`, `staffChat`, `commandspy`)
|
||||||
|
VALUES (:uuid, :name, :login, :prefix, :staffChat, :commandSpy)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
`last_known_name` = VALUES(`last_known_name`),
|
||||||
|
`login_msg` = VALUES(`login_msg`),
|
||||||
|
`prefix` = VALUES(`prefix`),
|
||||||
|
`staffChat` = VALUES(`staffChat`),
|
||||||
|
`commandspy` = VALUES(`commandspy`)
|
||||||
|
""";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public String getDisplayName()
|
public String getDisplayName()
|
||||||
{
|
{
|
||||||
return displayName;
|
return displayName;
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package dev.plex.storage.database;
|
package dev.plex.storage.database;
|
||||||
|
|
||||||
import com.j256.ormlite.jdbc.DataSourceConnectionSource;
|
|
||||||
import com.j256.ormlite.support.ConnectionSource;
|
|
||||||
import com.zaxxer.hikari.HikariConfig;
|
import com.zaxxer.hikari.HikariConfig;
|
||||||
import com.zaxxer.hikari.HikariDataSource;
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
import dev.plex.Plex;
|
import dev.plex.Plex;
|
||||||
import dev.plex.storage.StorageType;
|
import dev.plex.storage.StorageType;
|
||||||
import dev.plex.util.PlexLog;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -16,7 +14,7 @@ public class Database
|
|||||||
{
|
{
|
||||||
protected final Plex plugin;
|
protected final Plex plugin;
|
||||||
private final HikariDataSource dataSource;
|
private final HikariDataSource dataSource;
|
||||||
private final ConnectionSource connectionSource;
|
private final Jdbi jdbi;
|
||||||
private final StorageType storageType;
|
private final StorageType storageType;
|
||||||
private final MigrationRunner migrationRunner;
|
private final MigrationRunner migrationRunner;
|
||||||
|
|
||||||
@@ -39,9 +37,9 @@ public class Database
|
|||||||
this.dataSource = new HikariDataSource(config);
|
this.dataSource = new HikariDataSource(config);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.connectionSource = new DataSourceConnectionSource(dataSource, config.getJdbcUrl());
|
|
||||||
this.migrationRunner = new MigrationRunner(storageType);
|
this.migrationRunner = new MigrationRunner(storageType);
|
||||||
this.migrationRunner.runCore(dataSource, getClass().getClassLoader(), List.of("001_initial_schema"));
|
this.migrationRunner.runCore(dataSource, getClass().getClassLoader(), List.of("001_initial_schema"));
|
||||||
|
this.jdbi = Jdbi.create(dataSource);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -57,14 +55,6 @@ public class Database
|
|||||||
|
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
try
|
|
||||||
{
|
|
||||||
connectionSource.close();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
PlexLog.warn("Failed to close ORMLite connection source: " + e.getMessage());
|
|
||||||
}
|
|
||||||
dataSource.close();
|
dataSource.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,17 @@
|
|||||||
package dev.plex.storage.database.entity;
|
package dev.plex.storage.database.entity;
|
||||||
|
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@DatabaseTable(tableName = "notes")
|
|
||||||
public class NoteEntity
|
public class NoteEntity
|
||||||
{
|
{
|
||||||
@DatabaseField(generatedId = true, columnName = "row_id")
|
|
||||||
private long rowId;
|
private long rowId;
|
||||||
|
|
||||||
@DatabaseField(columnName = "id", index = true)
|
|
||||||
private int id;
|
private int id;
|
||||||
|
|
||||||
@DatabaseField(columnName = "uuid", canBeNull = false, index = true, width = 46)
|
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
@DatabaseField(columnName = "written_by_uuid", width = 46)
|
|
||||||
private String writtenByUuid;
|
private String writtenByUuid;
|
||||||
|
|
||||||
@DatabaseField(columnName = "note", width = 2000)
|
|
||||||
private String note;
|
private String note;
|
||||||
|
|
||||||
@DatabaseField(columnName = "timestamp")
|
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
|
|
||||||
public NoteEntity()
|
public NoteEntity()
|
||||||
|
|||||||
@@ -1,34 +1,17 @@
|
|||||||
package dev.plex.storage.database.entity;
|
package dev.plex.storage.database.entity;
|
||||||
|
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@DatabaseTable(tableName = "players")
|
|
||||||
public class PlayerEntity
|
public class PlayerEntity
|
||||||
{
|
{
|
||||||
@DatabaseField(id = true, columnName = "uuid", width = 46)
|
|
||||||
private String uuid;
|
private String uuid;
|
||||||
|
|
||||||
@DatabaseField(columnName = "last_known_name", width = 18, index = true)
|
|
||||||
private String lastKnownName;
|
private String lastKnownName;
|
||||||
|
|
||||||
@DatabaseField(columnName = "login_msg", width = 2000)
|
|
||||||
private String loginMessage;
|
private String loginMessage;
|
||||||
|
|
||||||
@DatabaseField(columnName = "prefix", width = 2000)
|
|
||||||
private String prefix;
|
private String prefix;
|
||||||
|
|
||||||
@DatabaseField(columnName = "staffChat")
|
|
||||||
private boolean staffChat;
|
private boolean staffChat;
|
||||||
|
|
||||||
@DatabaseField(columnName = "ips", width = 2000)
|
|
||||||
private String ips;
|
|
||||||
|
|
||||||
@DatabaseField(columnName = "commandspy")
|
|
||||||
private boolean commandSpy;
|
private boolean commandSpy;
|
||||||
|
|
||||||
public PlayerEntity()
|
public PlayerEntity()
|
||||||
|
|||||||
@@ -1,22 +1,14 @@
|
|||||||
package dev.plex.storage.database.entity;
|
package dev.plex.storage.database.entity;
|
||||||
|
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@DatabaseTable(tableName = "player_ips")
|
|
||||||
public class PlayerIpEntity
|
public class PlayerIpEntity
|
||||||
{
|
{
|
||||||
@DatabaseField(generatedId = true, columnName = "id")
|
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
@DatabaseField(columnName = "player_uuid", canBeNull = false, index = true, width = 46)
|
|
||||||
private String playerUuid;
|
private String playerUuid;
|
||||||
|
|
||||||
@DatabaseField(columnName = "ip", canBeNull = false, index = true, width = 64)
|
|
||||||
private String ip;
|
private String ip;
|
||||||
|
|
||||||
public PlayerIpEntity()
|
public PlayerIpEntity()
|
||||||
|
|||||||
@@ -1,49 +1,23 @@
|
|||||||
package dev.plex.storage.database.entity;
|
package dev.plex.storage.database.entity;
|
||||||
|
|
||||||
import com.j256.ormlite.field.DatabaseField;
|
|
||||||
import com.j256.ormlite.table.DatabaseTable;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@DatabaseTable(tableName = "punishments")
|
|
||||||
public class PunishmentEntity
|
public class PunishmentEntity
|
||||||
{
|
{
|
||||||
@DatabaseField(generatedId = true, columnName = "id")
|
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
@DatabaseField(columnName = "punished_uuid", canBeNull = false, index = true, width = 46)
|
|
||||||
private String punishedUuid;
|
private String punishedUuid;
|
||||||
|
|
||||||
@DatabaseField(columnName = "punisher_uuid", width = 46)
|
|
||||||
private String punisherUuid;
|
private String punisherUuid;
|
||||||
|
|
||||||
@DatabaseField(columnName = "source", width = 20)
|
|
||||||
private String source;
|
private String source;
|
||||||
|
|
||||||
@DatabaseField(columnName = "punisher_reference", width = 200)
|
|
||||||
private String punisherReference;
|
private String punisherReference;
|
||||||
|
|
||||||
@DatabaseField(columnName = "ip", width = 2000, index = true)
|
|
||||||
private String ip;
|
private String ip;
|
||||||
|
|
||||||
@DatabaseField(columnName = "type", width = 30)
|
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
@DatabaseField(columnName = "reason", width = 2000)
|
|
||||||
private String reason;
|
private String reason;
|
||||||
|
|
||||||
@DatabaseField(columnName = "customTime")
|
|
||||||
private boolean customTime;
|
private boolean customTime;
|
||||||
|
|
||||||
@DatabaseField(columnName = "active", index = true)
|
|
||||||
private boolean active;
|
private boolean active;
|
||||||
|
|
||||||
@DatabaseField(columnName = "issueDate")
|
|
||||||
private long issueDate;
|
private long issueDate;
|
||||||
|
|
||||||
@DatabaseField(columnName = "endDate")
|
|
||||||
private long endDate;
|
private long endDate;
|
||||||
|
|
||||||
public PunishmentEntity()
|
public PunishmentEntity()
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public class ServerModuleMigrations implements ModuleMigrations
|
|||||||
@Override
|
@Override
|
||||||
public void run(String resourceRoot, List<String> versions) throws SQLException
|
public void run(String resourceRoot, List<String> versions) throws SQLException
|
||||||
{
|
{
|
||||||
plugin.getSqlConnection().getMigrationRunner().runModule(
|
plugin.getDatabase().getMigrationRunner().runModule(
|
||||||
plugin.getSqlConnection().getDataSource(),
|
plugin.getDatabase().getDataSource(),
|
||||||
module,
|
module,
|
||||||
storage.scope(),
|
storage.scope(),
|
||||||
resourceRoot,
|
resourceRoot,
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
package dev.plex.storage.module;
|
|
||||||
|
|
||||||
import com.j256.ormlite.dao.Dao;
|
|
||||||
import com.j256.ormlite.dao.DaoManager;
|
|
||||||
import com.j256.ormlite.support.ConnectionSource;
|
|
||||||
import com.j256.ormlite.table.DatabaseTableConfig;
|
|
||||||
import dev.plex.api.storage.ModuleOrm;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public class ServerModuleOrm implements ModuleOrm
|
|
||||||
{
|
|
||||||
private final ConnectionSource connectionSource;
|
|
||||||
private final ServerModuleStorage storage;
|
|
||||||
private final Map<String, Dao<?, ?>> daos = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
public ServerModuleOrm(ConnectionSource connectionSource, ServerModuleStorage storage)
|
|
||||||
{
|
|
||||||
this.connectionSource = connectionSource;
|
|
||||||
this.storage = storage;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T, ID> Dao<T, ID> dao(Class<T> entityClass, String localTableName) throws SQLException
|
|
||||||
{
|
|
||||||
String key = entityClass.getName() + ":" + localTableName;
|
|
||||||
Dao<?, ?> existing = daos.get(key);
|
|
||||||
if (existing != null)
|
|
||||||
{
|
|
||||||
return (Dao<T, ID>) existing;
|
|
||||||
}
|
|
||||||
|
|
||||||
DatabaseTableConfig<T> tableConfig = DatabaseTableConfig.fromClass(connectionSource.getDatabaseType(), entityClass);
|
|
||||||
tableConfig.setTableName(storage.table(localTableName));
|
|
||||||
Dao<T, ID> dao = DaoManager.createDao(connectionSource, tableConfig);
|
|
||||||
daos.put(key, dao);
|
|
||||||
return dao;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
package dev.plex.storage.module;
|
package dev.plex.storage.module;
|
||||||
|
|
||||||
import com.j256.ormlite.misc.TransactionManager;
|
|
||||||
import dev.plex.Plex;
|
import dev.plex.Plex;
|
||||||
import dev.plex.api.storage.ModuleMigrations;
|
import dev.plex.api.storage.ModuleMigrations;
|
||||||
import dev.plex.api.storage.ModuleOrm;
|
|
||||||
import dev.plex.api.storage.ModuleStorage;
|
import dev.plex.api.storage.ModuleStorage;
|
||||||
import dev.plex.api.storage.SqlCallable;
|
|
||||||
import dev.plex.module.PlexModule;
|
import dev.plex.module.PlexModule;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
public class ServerModuleStorage implements ModuleStorage
|
public class ServerModuleStorage implements ModuleStorage
|
||||||
{
|
{
|
||||||
@@ -16,7 +12,6 @@ public class ServerModuleStorage implements ModuleStorage
|
|||||||
private final PlexModule module;
|
private final PlexModule module;
|
||||||
private final String prefix;
|
private final String prefix;
|
||||||
private final ModuleMigrations migrations;
|
private final ModuleMigrations migrations;
|
||||||
private final ModuleOrm orm;
|
|
||||||
|
|
||||||
public ServerModuleStorage(Plex plugin, PlexModule module)
|
public ServerModuleStorage(Plex plugin, PlexModule module)
|
||||||
{
|
{
|
||||||
@@ -24,7 +19,6 @@ public class ServerModuleStorage implements ModuleStorage
|
|||||||
this.module = module;
|
this.module = module;
|
||||||
this.prefix = ModuleNames.prefix(module);
|
this.prefix = ModuleNames.prefix(module);
|
||||||
this.migrations = new ServerModuleMigrations(plugin, module, this);
|
this.migrations = new ServerModuleMigrations(plugin, module, this);
|
||||||
this.orm = new ServerModuleOrm(plugin.getSqlConnection().getConnectionSource(), this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -56,14 +50,8 @@ public class ServerModuleStorage implements ModuleStorage
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ModuleOrm orm()
|
public Jdbi jdbi()
|
||||||
{
|
{
|
||||||
return orm;
|
return plugin.getDatabase().getJdbi();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T transaction(SqlCallable<T> callable) throws SQLException
|
|
||||||
{
|
|
||||||
return TransactionManager.callInTransaction(plugin.getSqlConnection().getConnectionSource(), callable::call);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,54 +1,44 @@
|
|||||||
package dev.plex.storage.player;
|
package dev.plex.storage.player;
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.j256.ormlite.dao.Dao;
|
|
||||||
import com.j256.ormlite.dao.DaoManager;
|
|
||||||
import com.j256.ormlite.support.ConnectionSource;
|
|
||||||
import com.j256.ormlite.stmt.DeleteBuilder;
|
|
||||||
import dev.plex.player.PlexPlayer;
|
import dev.plex.player.PlexPlayer;
|
||||||
|
import dev.plex.storage.StorageType;
|
||||||
import dev.plex.storage.database.entity.PlayerEntity;
|
import dev.plex.storage.database.entity.PlayerEntity;
|
||||||
import dev.plex.storage.database.entity.PlayerIpEntity;
|
|
||||||
import dev.plex.storage.repository.PlayerRepository;
|
import dev.plex.storage.repository.PlayerRepository;
|
||||||
import dev.plex.storage.repository.PunishmentRepository;
|
import dev.plex.storage.repository.PunishmentRepository;
|
||||||
|
import dev.plex.util.PlexLog;
|
||||||
|
import org.jdbi.v3.core.Handle;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
import org.jdbi.v3.core.JdbiException;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player persistence backed by ORMLite.
|
* Player persistence backed by JDBI.
|
||||||
*/
|
*/
|
||||||
public class SQLPlayerData implements PlayerRepository
|
public class SQLPlayerData implements PlayerRepository
|
||||||
{
|
{
|
||||||
private static final Gson GSON = new Gson();
|
private final Jdbi jdbi;
|
||||||
private final Dao<PlayerEntity, String> players;
|
|
||||||
private final Dao<PlayerIpEntity, Long> playerIps;
|
|
||||||
private final PunishmentRepository punishmentRepository;
|
private final PunishmentRepository punishmentRepository;
|
||||||
|
private final StorageType storageType;
|
||||||
|
|
||||||
public SQLPlayerData(ConnectionSource connectionSource, PunishmentRepository punishmentRepository)
|
public SQLPlayerData(Jdbi jdbi, PunishmentRepository punishmentRepository, StorageType storageType)
|
||||||
{
|
{
|
||||||
|
this.jdbi = jdbi;
|
||||||
this.punishmentRepository = punishmentRepository;
|
this.punishmentRepository = punishmentRepository;
|
||||||
try
|
this.storageType = storageType;
|
||||||
{
|
|
||||||
this.players = DaoManager.createDao(connectionSource, PlayerEntity.class);
|
|
||||||
this.playerIps = DaoManager.createDao(connectionSource, PlayerIpEntity.class);
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Failed to create player DAOs", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean exists(UUID uuid)
|
public boolean exists(UUID uuid)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return players.idExists(uuid.toString());
|
return jdbi.withHandle(h -> h.createQuery("SELECT 1 FROM players WHERE uuid = :u")
|
||||||
|
.bind("u", uuid.toString()).mapTo(Integer.class).findFirst().isPresent());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to check player existence for {0}: {1}", uuid, e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,11 +47,12 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return players.queryBuilder().where().eq("last_known_name", username).queryForFirst() != null;
|
return jdbi.withHandle(h -> h.createQuery("SELECT 1 FROM players WHERE last_known_name = :n")
|
||||||
|
.bind("n", username).mapTo(Integer.class).findFirst().isPresent());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to check player existence for {0}: {1}", username, e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,11 +61,16 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return toPlayer(players.queryForId(uuid.toString()), loadExtraData);
|
return jdbi.withHandle(h ->
|
||||||
|
{
|
||||||
|
PlayerEntity e = h.createQuery("SELECT * FROM players WHERE uuid = :u")
|
||||||
|
.bind("u", uuid.toString()).map((rs, ctx) -> mapRow(rs)).findFirst().orElse(null);
|
||||||
|
return toPlayer(h, e, loadExtraData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load player by UUID {0}: {1}", uuid, e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,12 +79,12 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PlayerEntity entity = players.queryForId(uuid.toString());
|
return jdbi.withHandle(h -> h.createQuery("SELECT last_known_name FROM players WHERE uuid = :u")
|
||||||
return entity == null ? null : entity.getLastKnownName();
|
.bind("u", uuid.toString()).mapTo(String.class).findFirst().orElse(null));
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load player name by UUID {0}: {1}", uuid, e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,11 +98,16 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return toPlayer(players.queryBuilder().limit(1L).where().eq("last_known_name", username).queryForFirst(), loadExtraData);
|
return jdbi.withHandle(h ->
|
||||||
|
{
|
||||||
|
PlayerEntity e = h.createQuery("SELECT * FROM players WHERE last_known_name = :n LIMIT 1")
|
||||||
|
.bind("n", username).map((rs, ctx) -> mapRow(rs)).findFirst().orElse(null);
|
||||||
|
return toPlayer(h, e, loadExtraData);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load player by name {0}: {1}", username, e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,39 +121,46 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
PlayerIpEntity playerIp = playerIps.queryBuilder().limit(1L).where().eq("ip", ip).queryForFirst();
|
return jdbi.withHandle(h ->
|
||||||
if (playerIp != null)
|
|
||||||
{
|
{
|
||||||
return toPlayer(players.queryForId(playerIp.getPlayerUuid()), true);
|
String uuid = h.createQuery("SELECT player_uuid FROM player_ips WHERE ip = :ip LIMIT 1")
|
||||||
}
|
.bind("ip", ip).mapTo(String.class).findFirst().orElse(null);
|
||||||
|
if (uuid == null)
|
||||||
for (PlayerEntity entity : players.queryForAll())
|
|
||||||
{
|
|
||||||
List<String> ips = parseIps(entity.getIps());
|
|
||||||
if (ips.contains(ip))
|
|
||||||
{
|
{
|
||||||
syncIps(entity.getUuid(), ips);
|
return null;
|
||||||
return toPlayer(entity, true);
|
|
||||||
}
|
}
|
||||||
}
|
PlayerEntity e = h.createQuery("SELECT * FROM players WHERE uuid = :u")
|
||||||
|
.bind("u", uuid).map((rs, ctx) -> mapRow(rs)).findFirst().orElse(null);
|
||||||
|
return toPlayer(h, e, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load player by IP {0}: {1}", ip, e.getMessage());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(PlexPlayer player)
|
public void update(PlexPlayer player)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
players.createOrUpdate(toEntity(player));
|
jdbi.useTransaction(h ->
|
||||||
syncIps(player.getUuid().toString(), player.getIps());
|
{
|
||||||
|
h.createUpdate(storageType.playerUpsertSql())
|
||||||
|
.bind("uuid", player.getUuid().toString())
|
||||||
|
.bind("name", player.getName())
|
||||||
|
.bind("login", player.getLoginMessage())
|
||||||
|
.bind("prefix", player.getPrefix())
|
||||||
|
.bind("staffChat", player.isStaffChat())
|
||||||
|
.bind("commandSpy", player.isCommandSpy())
|
||||||
|
.execute();
|
||||||
|
syncIps(h, player.getUuid().toString(), player.getIps());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to update player {0}: {1}", player.getUuid(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +169,35 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
update(player);
|
update(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlexPlayer toPlayer(PlayerEntity entity, boolean loadExtraData)
|
private static PlayerEntity mapRow(java.sql.ResultSet rs) throws java.sql.SQLException
|
||||||
|
{
|
||||||
|
PlayerEntity e = new PlayerEntity();
|
||||||
|
e.setUuid(rs.getString("uuid"));
|
||||||
|
e.setLastKnownName(rs.getString("last_known_name"));
|
||||||
|
e.setLoginMessage(rs.getString("login_msg"));
|
||||||
|
e.setPrefix(rs.getString("prefix"));
|
||||||
|
e.setStaffChat(rs.getBoolean("staffChat"));
|
||||||
|
e.setCommandSpy(rs.getBoolean("commandspy"));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> loadIps(Handle h, String uuid)
|
||||||
|
{
|
||||||
|
return h.createQuery("SELECT ip FROM player_ips WHERE player_uuid = :u")
|
||||||
|
.bind("u", uuid).mapTo(String.class).list();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncIps(Handle h, String playerUuid, List<String> ips)
|
||||||
|
{
|
||||||
|
h.createUpdate("DELETE FROM player_ips WHERE player_uuid = :u").bind("u", playerUuid).execute();
|
||||||
|
for (String ip : ips.stream().distinct().toList())
|
||||||
|
{
|
||||||
|
h.createUpdate("INSERT INTO player_ips (player_uuid, ip) VALUES (:u, :ip)")
|
||||||
|
.bind("u", playerUuid).bind("ip", ip).execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlexPlayer toPlayer(Handle h, PlayerEntity entity, boolean loadExtraData)
|
||||||
{
|
{
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
{
|
{
|
||||||
@@ -173,7 +209,7 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
plexPlayer.setLoginMessage(entity.getLoginMessage());
|
plexPlayer.setLoginMessage(entity.getLoginMessage());
|
||||||
plexPlayer.setPrefix(entity.getPrefix());
|
plexPlayer.setPrefix(entity.getPrefix());
|
||||||
plexPlayer.setStaffChat(entity.isStaffChat());
|
plexPlayer.setStaffChat(entity.isStaffChat());
|
||||||
plexPlayer.setIps(parseIps(entity.getIps()));
|
plexPlayer.setIps(loadIps(h, entity.getUuid()));
|
||||||
plexPlayer.setCommandSpy(entity.isCommandSpy());
|
plexPlayer.setCommandSpy(entity.isCommandSpy());
|
||||||
if (loadExtraData)
|
if (loadExtraData)
|
||||||
{
|
{
|
||||||
@@ -182,41 +218,4 @@ public class SQLPlayerData implements PlayerRepository
|
|||||||
}
|
}
|
||||||
return plexPlayer;
|
return plexPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayerEntity toEntity(PlexPlayer player)
|
|
||||||
{
|
|
||||||
PlayerEntity entity = new PlayerEntity();
|
|
||||||
entity.setUuid(player.getUuid().toString());
|
|
||||||
entity.setLastKnownName(player.getName());
|
|
||||||
entity.setLoginMessage(player.getLoginMessage());
|
|
||||||
entity.setPrefix(player.getPrefix());
|
|
||||||
entity.setStaffChat(player.isStaffChat());
|
|
||||||
entity.setIps(GSON.toJson(player.getIps()));
|
|
||||||
entity.setCommandSpy(player.isCommandSpy());
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> parseIps(String ips)
|
|
||||||
{
|
|
||||||
if (ips == null || ips.isBlank())
|
|
||||||
{
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
List<String> parsed = GSON.fromJson(ips, new TypeToken<List<String>>()
|
|
||||||
{
|
|
||||||
}.getType());
|
|
||||||
return parsed == null ? List.of() : parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void syncIps(String playerUuid, List<String> ips) throws SQLException
|
|
||||||
{
|
|
||||||
DeleteBuilder<PlayerIpEntity, Long> delete = playerIps.deleteBuilder();
|
|
||||||
delete.where().eq("player_uuid", playerUuid);
|
|
||||||
delete.delete();
|
|
||||||
|
|
||||||
for (String ip : ips.stream().distinct().toList())
|
|
||||||
{
|
|
||||||
playerIps.create(new PlayerIpEntity(playerUuid, ip));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,48 +3,41 @@ package dev.plex.storage.player;
|
|||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import dev.plex.storage.SQLConnection;
|
|
||||||
import dev.plex.storage.StorageType;
|
import dev.plex.storage.StorageType;
|
||||||
|
import dev.plex.util.PlexLog;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
import org.jdbi.v3.core.JdbiException;
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class SQLPlayerModuleData implements PlayerModuleDataRepository
|
public class SQLPlayerModuleData implements PlayerModuleDataRepository
|
||||||
{
|
{
|
||||||
private final SQLConnection sqlConnection;
|
private final Jdbi jdbi;
|
||||||
private final StorageType storageType;
|
private final StorageType storageType;
|
||||||
|
|
||||||
public SQLPlayerModuleData(SQLConnection sqlConnection, StorageType storageType)
|
public SQLPlayerModuleData(Jdbi jdbi, StorageType storageType)
|
||||||
{
|
{
|
||||||
this.sqlConnection = sqlConnection;
|
this.jdbi = jdbi;
|
||||||
this.storageType = storageType;
|
this.storageType = storageType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<JsonElement> get(UUID playerUuid, String module, String key)
|
public Optional<JsonElement> get(UUID playerUuid, String module, String key)
|
||||||
{
|
{
|
||||||
String sql = "SELECT value_json FROM player_module_data WHERE player_uuid = ? AND module = ? AND data_key = ?";
|
try
|
||||||
try (Connection connection = sqlConnection.getConnection(); PreparedStatement statement = connection.prepareStatement(sql))
|
|
||||||
{
|
{
|
||||||
statement.setString(1, playerUuid.toString());
|
return jdbi.withHandle(h -> h.createQuery(
|
||||||
statement.setString(2, module);
|
"SELECT value_json FROM player_module_data WHERE player_uuid = :p AND module = :m AND data_key = :k")
|
||||||
statement.setString(3, key);
|
.bind("p", playerUuid.toString())
|
||||||
try (ResultSet resultSet = statement.executeQuery())
|
.bind("m", module)
|
||||||
{
|
.bind("k", key)
|
||||||
if (!resultSet.next())
|
.mapTo(String.class).findFirst())
|
||||||
{
|
.map(JsonParser::parseString);
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
return Optional.of(JsonParser.parseString(resultSet.getString("value_json")));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (SQLException | JsonSyntaxException e)
|
catch (JdbiException | JsonSyntaxException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load player module data {0}/{1}/{2}: {3}", playerUuid, module, key, e.getMessage());
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,35 +45,37 @@ public class SQLPlayerModuleData implements PlayerModuleDataRepository
|
|||||||
@Override
|
@Override
|
||||||
public void set(UUID playerUuid, String module, String key, JsonElement value)
|
public void set(UUID playerUuid, String module, String key, JsonElement value)
|
||||||
{
|
{
|
||||||
try (Connection connection = sqlConnection.getConnection(); PreparedStatement statement = connection.prepareStatement(storageType.playerModuleDataUpsertSql()))
|
try
|
||||||
{
|
{
|
||||||
statement.setString(1, playerUuid.toString());
|
jdbi.useHandle(h -> h.createUpdate(storageType.playerModuleDataUpsertSql())
|
||||||
statement.setString(2, module);
|
.bind(0, playerUuid.toString())
|
||||||
statement.setString(3, key);
|
.bind(1, module)
|
||||||
statement.setString(4, value.toString());
|
.bind(2, key)
|
||||||
statement.setLong(5, System.currentTimeMillis());
|
.bind(3, value.toString())
|
||||||
statement.executeUpdate();
|
.bind(4, System.currentTimeMillis())
|
||||||
|
.execute());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to save player module data {0}/{1}/{2}: {3}", playerUuid, module, key, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove(UUID playerUuid, String module, String key)
|
public void remove(UUID playerUuid, String module, String key)
|
||||||
{
|
{
|
||||||
String sql = "DELETE FROM player_module_data WHERE player_uuid = ? AND module = ? AND data_key = ?";
|
try
|
||||||
try (Connection connection = sqlConnection.getConnection(); PreparedStatement statement = connection.prepareStatement(sql))
|
|
||||||
{
|
{
|
||||||
statement.setString(1, playerUuid.toString());
|
jdbi.useHandle(h -> h.createUpdate(
|
||||||
statement.setString(2, module);
|
"DELETE FROM player_module_data WHERE player_uuid = :p AND module = :m AND data_key = :k")
|
||||||
statement.setString(3, key);
|
.bind("p", playerUuid.toString())
|
||||||
statement.executeUpdate();
|
.bind("m", module)
|
||||||
|
.bind("k", key)
|
||||||
|
.execute());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to remove player module data {0}/{1}/{2}: {3}", playerUuid, module, key, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
package dev.plex.storage.punishment;
|
package dev.plex.storage.punishment;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.j256.ormlite.dao.Dao;
|
|
||||||
import com.j256.ormlite.dao.DaoManager;
|
|
||||||
import com.j256.ormlite.support.ConnectionSource;
|
|
||||||
import com.j256.ormlite.stmt.DeleteBuilder;
|
|
||||||
import dev.plex.punishment.extra.Note;
|
import dev.plex.punishment.extra.Note;
|
||||||
import dev.plex.storage.database.entity.NoteEntity;
|
import dev.plex.storage.database.entity.NoteEntity;
|
||||||
import dev.plex.storage.repository.NoteRepository;
|
import dev.plex.storage.repository.NoteRepository;
|
||||||
|
import dev.plex.util.PlexLog;
|
||||||
import dev.plex.util.TimeUtils;
|
import dev.plex.util.TimeUtils;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
import org.jdbi.v3.core.JdbiException;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
@@ -23,20 +21,13 @@ import java.util.concurrent.Executor;
|
|||||||
|
|
||||||
public class SQLNotes implements NoteRepository
|
public class SQLNotes implements NoteRepository
|
||||||
{
|
{
|
||||||
private final Dao<NoteEntity, Long> notes;
|
private final Jdbi jdbi;
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
|
|
||||||
public SQLNotes(ConnectionSource connectionSource, Executor executor)
|
public SQLNotes(Jdbi jdbi, Executor executor)
|
||||||
{
|
{
|
||||||
try
|
this.jdbi = jdbi;
|
||||||
{
|
this.executor = executor;
|
||||||
this.notes = DaoManager.createDao(connectionSource, NoteEntity.class);
|
|
||||||
this.executor = executor;
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Failed to create note DAO", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<List<Note>> getNotes(UUID uuid)
|
public CompletableFuture<List<Note>> getNotes(UUID uuid)
|
||||||
@@ -45,15 +36,16 @@ public class SQLNotes implements NoteRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return notes.queryForEq("uuid", uuid.toString()).stream()
|
return jdbi.withHandle(h -> h.createQuery("SELECT * FROM notes WHERE uuid = :u")
|
||||||
|
.bind("u", uuid.toString()).map((rs, ctx) -> mapRow(rs)).list()).stream()
|
||||||
.sorted(Comparator.comparingInt(NoteEntity::getId))
|
.sorted(Comparator.comparingInt(NoteEntity::getId))
|
||||||
.map(this::toNote)
|
.map(this::toNote)
|
||||||
.flatMap(Optional::stream)
|
.flatMap(Optional::stream)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load notes for {0}: {1}", uuid, e.getMessage());
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
}, executor);
|
}, executor);
|
||||||
@@ -65,13 +57,14 @@ public class SQLNotes implements NoteRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DeleteBuilder<NoteEntity, Long> delete = notes.deleteBuilder();
|
jdbi.useHandle(h -> h.createUpdate("DELETE FROM notes WHERE uuid = :u AND id = :id")
|
||||||
delete.where().eq("uuid", uuid.toString()).and().eq("id", id);
|
.bind("u", uuid.toString())
|
||||||
delete.delete();
|
.bind("id", id)
|
||||||
|
.execute());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to delete note {0} for {1}: {2}", id, uuid, e.getMessage());
|
||||||
}
|
}
|
||||||
}, executor);
|
}, executor);
|
||||||
}
|
}
|
||||||
@@ -82,22 +75,40 @@ public class SQLNotes implements NoteRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int nextId = notes.queryForEq("uuid", note.getUuid().toString()).stream()
|
int nextId = jdbi.withHandle(h -> h.createQuery("SELECT COALESCE(MAX(id), 0) FROM notes WHERE uuid = :u")
|
||||||
.map(NoteEntity::getId)
|
.bind("u", note.getUuid().toString()).mapTo(Integer.class).one()) + 1;
|
||||||
.max(Integer::compareTo)
|
|
||||||
.orElse(0) + 1;
|
|
||||||
NoteEntity entity = toEntity(note);
|
NoteEntity entity = toEntity(note);
|
||||||
entity.setId(nextId);
|
entity.setId(nextId);
|
||||||
notes.create(entity);
|
jdbi.useHandle(h -> h.createUpdate(
|
||||||
|
"INSERT INTO notes (id, uuid, written_by_uuid, note, timestamp) " +
|
||||||
|
"VALUES (:id, :uuid, :writtenBy, :note, :ts)")
|
||||||
|
.bind("id", entity.getId())
|
||||||
|
.bind("uuid", entity.getUuid())
|
||||||
|
.bind("writtenBy", entity.getWrittenByUuid())
|
||||||
|
.bind("note", entity.getNote())
|
||||||
|
.bind("ts", entity.getTimestamp())
|
||||||
|
.execute());
|
||||||
note.setId(nextId);
|
note.setId(nextId);
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to add note for {0}: {1}", note.getUuid(), e.getMessage());
|
||||||
}
|
}
|
||||||
}, executor);
|
}, executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static NoteEntity mapRow(java.sql.ResultSet rs) throws java.sql.SQLException
|
||||||
|
{
|
||||||
|
NoteEntity e = new NoteEntity();
|
||||||
|
e.setRowId(rs.getLong("row_id"));
|
||||||
|
e.setId(rs.getInt("id"));
|
||||||
|
e.setUuid(rs.getString("uuid"));
|
||||||
|
e.setWrittenByUuid(rs.getString("written_by_uuid"));
|
||||||
|
e.setNote(rs.getString("note"));
|
||||||
|
e.setTimestamp(rs.getLong("timestamp"));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
private Optional<Note> toNote(NoteEntity entity)
|
private Optional<Note> toNote(NoteEntity entity)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
package dev.plex.storage.punishment;
|
package dev.plex.storage.punishment;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.j256.ormlite.dao.Dao;
|
|
||||||
import com.j256.ormlite.dao.DaoManager;
|
|
||||||
import com.j256.ormlite.support.ConnectionSource;
|
|
||||||
import com.j256.ormlite.stmt.UpdateBuilder;
|
|
||||||
import dev.plex.api.punishment.PunishmentSource;
|
import dev.plex.api.punishment.PunishmentSource;
|
||||||
import dev.plex.punishment.Punishment;
|
import dev.plex.punishment.Punishment;
|
||||||
import dev.plex.punishment.PunishmentType;
|
import dev.plex.punishment.PunishmentType;
|
||||||
@@ -12,8 +8,9 @@ import dev.plex.storage.database.entity.PunishmentEntity;
|
|||||||
import dev.plex.storage.repository.PunishmentRepository;
|
import dev.plex.storage.repository.PunishmentRepository;
|
||||||
import dev.plex.util.PlexLog;
|
import dev.plex.util.PlexLog;
|
||||||
import dev.plex.util.TimeUtils;
|
import dev.plex.util.TimeUtils;
|
||||||
|
import org.jdbi.v3.core.Jdbi;
|
||||||
|
import org.jdbi.v3.core.JdbiException;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
@@ -24,20 +21,13 @@ import java.util.concurrent.Executor;
|
|||||||
|
|
||||||
public class SQLPunishment implements PunishmentRepository
|
public class SQLPunishment implements PunishmentRepository
|
||||||
{
|
{
|
||||||
private final Dao<PunishmentEntity, Long> punishments;
|
private final Jdbi jdbi;
|
||||||
private final Executor executor;
|
private final Executor executor;
|
||||||
|
|
||||||
public SQLPunishment(ConnectionSource connectionSource, Executor executor)
|
public SQLPunishment(Jdbi jdbi, Executor executor)
|
||||||
{
|
{
|
||||||
try
|
this.jdbi = jdbi;
|
||||||
{
|
this.executor = executor;
|
||||||
this.punishments = DaoManager.createDao(connectionSource, PunishmentEntity.class);
|
|
||||||
this.executor = executor;
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{
|
|
||||||
throw new IllegalStateException("Failed to create punishment DAO", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<List<Punishment>> getPunishments()
|
public CompletableFuture<List<Punishment>> getPunishments()
|
||||||
@@ -46,11 +36,12 @@ public class SQLPunishment implements PunishmentRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return punishments.queryForAll().stream().map(this::toPunishment).toList();
|
return jdbi.withHandle(h -> h.createQuery("SELECT * FROM punishments")
|
||||||
|
.map((rs, ctx) -> mapRow(rs)).list()).stream().map(this::toPunishment).toList();
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load punishments: {0}", e.getMessage());
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
}, executor);
|
}, executor);
|
||||||
@@ -60,11 +51,13 @@ public class SQLPunishment implements PunishmentRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return punishments.queryForEq("punished_uuid", uuid.toString()).stream().map(this::toPunishment).toList();
|
return jdbi.withHandle(h -> h.createQuery("SELECT * FROM punishments WHERE punished_uuid = :u")
|
||||||
|
.bind("u", uuid.toString()).map((rs, ctx) -> mapRow(rs)).list())
|
||||||
|
.stream().map(this::toPunishment).toList();
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load punishments for {0}: {1}", uuid, e.getMessage());
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,11 +66,13 @@ public class SQLPunishment implements PunishmentRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return punishments.queryForEq("ip", ip).stream().map(this::toPunishment).toList();
|
return jdbi.withHandle(h -> h.createQuery("SELECT * FROM punishments WHERE ip = :ip")
|
||||||
|
.bind("ip", ip).map((rs, ctx) -> mapRow(rs)).list())
|
||||||
|
.stream().map(this::toPunishment).toList();
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to load punishments for IP {0}: {1}", ip, e.getMessage());
|
||||||
return Lists.newArrayList();
|
return Lists.newArrayList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,11 +84,26 @@ public class SQLPunishment implements PunishmentRepository
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
PlexLog.debug("Persisting punishment for " + punishment.getPunished());
|
PlexLog.debug("Persisting punishment for " + punishment.getPunished());
|
||||||
punishments.create(toEntity(punishment));
|
PunishmentEntity e = toEntity(punishment);
|
||||||
|
jdbi.useHandle(h -> h.createUpdate(
|
||||||
|
"INSERT INTO punishments (punished_uuid, punisher_uuid, source, punisher_reference, ip, type, reason, customTime, active, issueDate, endDate) " +
|
||||||
|
"VALUES (:punishedUuid, :punisherUuid, :source, :punisherReference, :ip, :type, :reason, :customTime, :active, :issueDate, :endDate)")
|
||||||
|
.bind("punishedUuid", e.getPunishedUuid())
|
||||||
|
.bind("punisherUuid", e.getPunisherUuid())
|
||||||
|
.bind("source", e.getSource())
|
||||||
|
.bind("punisherReference", e.getPunisherReference())
|
||||||
|
.bind("ip", e.getIp())
|
||||||
|
.bind("type", e.getType())
|
||||||
|
.bind("reason", e.getReason())
|
||||||
|
.bind("customTime", e.isCustomTime())
|
||||||
|
.bind("active", e.isActive())
|
||||||
|
.bind("issueDate", e.getIssueDate())
|
||||||
|
.bind("endDate", e.getEndDate())
|
||||||
|
.execute());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to persist punishment for {0}: {1}", punishment.getPunished(), e.getMessage());
|
||||||
}
|
}
|
||||||
}, executor);
|
}, executor);
|
||||||
}
|
}
|
||||||
@@ -118,17 +128,37 @@ public class SQLPunishment implements PunishmentRepository
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UpdateBuilder<PunishmentEntity, Long> update = punishments.updateBuilder();
|
jdbi.useHandle(h -> h.createUpdate(
|
||||||
update.updateColumnValue("active", active);
|
"UPDATE punishments SET active = :active WHERE punished_uuid = :u AND type = :t")
|
||||||
update.where().eq("punished_uuid", punished.toString()).and().eq("type", type.name());
|
.bind("active", active)
|
||||||
update.update();
|
.bind("u", punished.toString())
|
||||||
|
.bind("t", type.name())
|
||||||
|
.execute());
|
||||||
}
|
}
|
||||||
catch (SQLException e)
|
catch (JdbiException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
PlexLog.warn("Failed to update punishment state for {0}: {1}", punished, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PunishmentEntity mapRow(java.sql.ResultSet rs) throws java.sql.SQLException
|
||||||
|
{
|
||||||
|
PunishmentEntity e = new PunishmentEntity();
|
||||||
|
e.setId(rs.getLong("id"));
|
||||||
|
e.setPunishedUuid(rs.getString("punished_uuid"));
|
||||||
|
e.setPunisherUuid(rs.getString("punisher_uuid"));
|
||||||
|
e.setSource(rs.getString("source"));
|
||||||
|
e.setPunisherReference(rs.getString("punisher_reference"));
|
||||||
|
e.setIp(rs.getString("ip"));
|
||||||
|
e.setType(rs.getString("type"));
|
||||||
|
e.setReason(rs.getString("reason"));
|
||||||
|
e.setCustomTime(rs.getBoolean("customTime"));
|
||||||
|
e.setActive(rs.getBoolean("active"));
|
||||||
|
e.setIssueDate(rs.getLong("issueDate"));
|
||||||
|
e.setEndDate(rs.getLong("endDate"));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
private Punishment toPunishment(PunishmentEntity entity)
|
private Punishment toPunishment(PunishmentEntity entity)
|
||||||
{
|
{
|
||||||
UUID punisher = entity.getPunisherUuid() == null || entity.getPunisherUuid().isBlank() ? null : UUID.fromString(entity.getPunisherUuid());
|
UUID punisher = entity.getPunisherUuid() == null || entity.getPunisherUuid().isBlank() ? null : UUID.fromString(entity.getPunisherUuid());
|
||||||
|
|||||||
@@ -88,9 +88,9 @@ public class PlexUtils
|
|||||||
|
|
||||||
public static void testConnections(Plex plugin)
|
public static void testConnections(Plex plugin)
|
||||||
{
|
{
|
||||||
if (plugin.getSqlConnection().getDataSource() != null)
|
if (plugin.getDatabase().getDataSource() != null)
|
||||||
{
|
{
|
||||||
try (Connection ignored = plugin.getSqlConnection().getCon())
|
try (Connection ignored = plugin.getDatabase().getConnection())
|
||||||
{
|
{
|
||||||
PlexLog.log("Successfully enabled " + plugin.getStorageType().getDisplayName() + "!");
|
PlexLog.log("Successfully enabled " + plugin.getStorageType().getDisplayName() + "!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ CREATE TABLE IF NOT EXISTS `players` (
|
|||||||
`login_msg` VARCHAR(2000),
|
`login_msg` VARCHAR(2000),
|
||||||
`prefix` VARCHAR(2000),
|
`prefix` VARCHAR(2000),
|
||||||
`staffChat` BOOLEAN,
|
`staffChat` BOOLEAN,
|
||||||
`ips` VARCHAR(2000),
|
|
||||||
`commandspy` BOOLEAN,
|
`commandspy` BOOLEAN,
|
||||||
PRIMARY KEY (`uuid`),
|
PRIMARY KEY (`uuid`),
|
||||||
INDEX `idx_players_last_known_name` (`last_known_name`)
|
INDEX `idx_players_last_known_name` (`last_known_name`)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ CREATE TABLE IF NOT EXISTS players (
|
|||||||
login_msg VARCHAR(2000),
|
login_msg VARCHAR(2000),
|
||||||
prefix VARCHAR(2000),
|
prefix VARCHAR(2000),
|
||||||
staffChat BOOLEAN,
|
staffChat BOOLEAN,
|
||||||
ips VARCHAR(2000),
|
|
||||||
commandspy BOOLEAN
|
commandspy BOOLEAN
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ CREATE TABLE IF NOT EXISTS players (
|
|||||||
login_msg VARCHAR(2000),
|
login_msg VARCHAR(2000),
|
||||||
prefix VARCHAR(2000),
|
prefix VARCHAR(2000),
|
||||||
staffChat BOOLEAN,
|
staffChat BOOLEAN,
|
||||||
ips VARCHAR(2000),
|
|
||||||
commandspy BOOLEAN
|
commandspy BOOLEAN
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user