-
Notifications
You must be signed in to change notification settings - Fork 0
4. Database System
VertexCore provides a unified abstraction layer for persistent plugin data.
Plugins interact with a common API while the underlying storage backend is selected through configuration.
Supported backends:
- JSON (flat file)
- H2
- MySQL / MariaDB
VertexCore stores data objects as JSON.
Only fields annotated with @DbExpose are serialized.
import de.tebrox.vertexCore.database.DataObject;
import de.tebrox.vertexCore.database.annotation.DbExpose;
import java.util.UUID;
public class PlayerProfile implements DataObject {
private String uniqueId;
@DbExpose
public UUID playerUuid;
@DbExpose
public int coins;
// Required by the JSON codec
public PlayerProfile() {
}
public PlayerProfile(UUID playerUuid, int coins) {
this.playerUuid = playerUuid;
this.coins = coins;
}
@Override
public String getUniqueId() {
return uniqueId;
}
@Override
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
}The recommended approach is to combine ConfigObject and DatabaseSettings in a single class.
This keeps configuration and database behavior together without requiring additional mapping or wrapper classes.
import de.tebrox.vertexCore.config.ConfigObject;
import de.tebrox.vertexCore.config.annotation.*;
import de.tebrox.vertexCore.database.DatabaseSettings;
@StoreAt("database.yml")
@ConfigComment("Database configuration for MyPlugin")
public final class MyDbSettings implements DatabaseSettings, ConfigObject {
@ConfigKey("backend")
@AllowedValues({"json", "h2", "mysql"})
@ConfigComment("Storage backend used by VertexCore")
public String backend = "json";
@ConfigKey("table-prefix")
@ConfigComment("Prefix for database tables")
public String tablePrefix = "myplugin_";
@ConfigKey("mysql.url")
@ConfigComment("JDBC URL (only used if backend=mysql)")
public String mysqlUrl =
"jdbc:mysql://localhost:3306/test?useSSL=false";
@ConfigKey("mysql.user")
public String mysqlUser = "root";
@ConfigKey("mysql.password")
public String mysqlPassword = "password";
@Override
public String backend() {
return backend;
}
@Override
public String tablePrefix() {
return tablePrefix;
}
@Override
public String mysqlUrl() {
return mysqlUrl;
}
@Override
public String mysqlUser() {
return mysqlUser;
}
@Override
public String mysqlPassword() {
return mysqlPassword;
}
}DatabaseSettings also provides optional defaults for:
- Queue usage
- Operation timeout
- Connection pool size
These can be overridden when required.
import de.tebrox.vertexCore.config.Config;
import de.tebrox.vertexCore.database.Database;
import org.bukkit.plugin.java.JavaPlugin;
public final class MyPlugin extends JavaPlugin {
private Config<MyDbSettings> dbConfig;
private MyDbSettings dbSettings;
private Database<PlayerProfile> database;
@Override
public void onEnable() {
this.dbConfig = new Config<>(this, MyDbSettings.class);
this.dbSettings = this.dbConfig.loadConfigObject();
this.database = new Database<>(
this,
dbSettings,
PlayerProfile.class
);
}
}The database configuration file is created automatically on first startup.
PlayerProfile profile =
new PlayerProfile(playerUuid, 100);
profile.setUniqueId(playerUuid.toString());
database.saveObject(profile);PlayerProfile loaded =
database.loadObject(playerUuid.toString());
if (loaded != null) {
int coins = loaded.coins;
}boolean exists =
database.objectExists(playerUuid.toString());database.deleteObject(playerUuid.toString());List<PlayerProfile> profiles =
database.loadObjects();VertexCore provides asynchronous helpers based on CompletableFuture.
database.loadObjectAsync(playerUuid.toString())
.thenAccept(profile -> {
if (profile != null) {
getLogger().info("Coins: " + profile.coins);
}
})
.exceptionally(err -> {
err.printStackTrace();
return null;
});If the result needs to be processed on the server's main thread:
database.loadObjectAsyncMain(
playerUuid.toString(),
profile -> {
if (profile != null) {
// Executed on the main thread
}
},
Throwable::printStackTrace
);VertexCore also provides corresponding helpers for saving objects and loading collections.
VertexCore 1.1.0 provides tracked database writes for cases where a plugin needs more information about the actual outcome of a write operation.
DatabaseWriteOperation operation =
database.saveObjectTrackedAsync(profile);Tracked writes expose the underlying write operation and its result instead of only providing a caller-facing completion state.
The normal APIs remain available:
database.saveObject(profile);and:
database.saveObjectAsync(profile);For most plugins, these standard methods are sufficient.
Tracked writes are primarily useful when stronger write-state handling or recovery logic is required.
VertexCore can reconcile the state of a previously tracked write for a specific object key.
database.reconcileObjectAsync(playerUuid.toString())
.thenAccept(result -> {
// Inspect reconciliation result
});This is useful for handling situations where the caller could not immediately determine whether a database write was committed.
To make a plugin available to VertexCore's migration commands, register its database settings and data classes.
import de.tebrox.vertexCore.VertexCoreApi;
VertexCoreApi.get().registry().register(
this,
() -> dbSettings,
PlayerProfile.class
);After registration, the plugin becomes selectable by VertexCore's migration system.
Database implements AutoCloseable.
A database instance can therefore be closed when the owning plugin no longer needs it:
database.close();VertexCore then closes resources associated with the owning plugin.
- Configure database settings using the Config System
- Register administrative commands using the Command System
- Return to Getting Started
- Return to the Wiki Home
VertexCore 1.1.0 · Repository · Releases · Issues