Database Bridge System
The Database Bridge system provides an abstraction layer for database operations in SuperiorSkyblock2. It supports multiple database backends (MySQL, SQLite) and handles data persistence for islands, players, and custom data.
Database Bridge Interface
The DatabaseBridge interface provides methods for CRUD operations:
import com.bgsoftware.superiorskyblock.api.data.DatabaseBridge;
import com.bgsoftware.superiorskyblock.api.data.DatabaseBridgeMode;
import com.bgsoftware.superiorskyblock.api.data.DatabaseFilter;
import com.bgsoftware.superiorskyblock.api.objects.Pair;
import java.util.Map;
import java.util.function.Consumer;
public class MyDataHandler {
private final DatabaseBridge databaseBridge;
public MyDataHandler(DatabaseBridge databaseBridge) {
this.databaseBridge = databaseBridge;
// Enable saving data
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.SAVE_DATA);
}
}
Database Bridge Modes
Control when the bridge saves data:
public enum DatabaseBridgeMode {
SAVE_DATA, // Execute database updates
IDLE // Skip updates, only allow reads
}
Mode Usage
// Enable data saving
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.SAVE_DATA);
// Disable data saving (useful during bulk operations)
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.IDLE);
// Check current mode
DatabaseBridgeMode currentMode = databaseBridge.getDatabaseBridgeMode();
Set mode to IDLE when loading data to prevent unnecessary write operations.
CRUD Operations
Insert Data
Insert new records into the database:
import com.bgsoftware.superiorskyblock.api.objects.Pair;
public void insertPlayer(UUID playerId, String playerName, int score) {
databaseBridge.insertObject(
"custom_players",
new Pair<>("uuid", playerId.toString()),
new Pair<>("name", playerName),
new Pair<>("score", score),
new Pair<>("created_at", System.currentTimeMillis())
);
}
Update Data
Update existing records with filters:
import com.bgsoftware.superiorskyblock.api.data.DatabaseFilter;
public void updatePlayerScore(UUID playerId, int newScore) {
DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
databaseBridge.updateObject(
"custom_players",
filter,
new Pair<>("score", newScore),
new Pair<>("updated_at", System.currentTimeMillis())
);
}
Delete Data
Remove records from the database:
public void deletePlayer(UUID playerId) {
DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
databaseBridge.deleteObject("custom_players", filter);
}
// Delete all records (use with caution)
public void clearAllData() {
databaseBridge.deleteObject("custom_players", null);
}
Load Data
Query and load data from the database:
public void loadPlayer(UUID playerId) {
DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
databaseBridge.loadObject("custom_players", filter, result -> {
String name = (String) result.get("name");
int score = (int) result.get("score");
long createdAt = (long) result.get("created_at");
// Process loaded data
System.out.println("Loaded player: " + name + " with score: " + score);
});
}
// Load all records
public void loadAllPlayers() {
databaseBridge.loadAllObjects("custom_players", result -> {
String uuid = (String) result.get("uuid");
String name = (String) result.get("name");
int score = (int) result.get("score");
// Process each record
players.put(UUID.fromString(uuid), new PlayerData(name, score));
});
}
Database Filters
Create filters for precise queries:
Single Filter
Filter by a single column:DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
Multiple Filters
Filter by multiple columns:List<Pair<String, Object>> filters = Arrays.asList(
new Pair<>("island_owner", ownerId.toString()),
new Pair<>("status", "active")
);
DatabaseFilter filter = DatabaseFilter.fromFilters(filters);
Iterate Filters
Process filter conditions:filter.forEach((column, value) -> {
System.out.println("Filter: " + column + " = " + value);
});
Batch Operations
Optimize performance with batch operations:
public void saveBulkData(List<PlayerData> players) {
// Enable batch mode
databaseBridge.batchOperations(true);
try {
for (PlayerData player : players) {
databaseBridge.insertObject(
"custom_players",
new Pair<>("uuid", player.getUuid().toString()),
new Pair<>("name", player.getName()),
new Pair<>("score", player.getScore())
);
}
} finally {
// Disable batch mode and flush
databaseBridge.batchOperations(false);
}
}
Always disable batch operations after bulk inserts to ensure data is flushed to the database.
Creating Custom Database Bridges
Extend database bridges for custom entities using DatabaseBridgeFactory:
import com.bgsoftware.superiorskyblock.api.factory.DatabaseBridgeFactory;
import com.bgsoftware.superiorskyblock.api.SuperiorSkyblock;
public class CustomDatabaseBridge implements DatabaseBridge {
private final DatabaseBridge original;
private final MyCustomObject object;
public CustomDatabaseBridge(MyCustomObject object, DatabaseBridge original) {
this.object = object;
this.original = original;
}
@Override
public void updateObject(String table, DatabaseFilter filter, Pair<String, Object>... columns) {
// Add custom logic before/after update
original.updateObject(table, filter, columns);
}
@Override
public void insertObject(String table, Pair<String, Object>... columns) {
// Add custom logic before/after insert
original.insertObject(table, columns);
}
@Override
public void deleteObject(String table, DatabaseFilter filter) {
// Add custom logic before/after delete
original.deleteObject(table, filter);
}
@Override
public void loadObject(String table, DatabaseFilter filter, Consumer<Map<String, Object>> resultConsumer) {
original.loadObject(table, filter, resultConsumer);
}
@Override
public void loadAllObjects(String table, Consumer<Map<String, Object>> resultConsumer) {
original.loadAllObjects(table, resultConsumer);
}
@Override
public void batchOperations(boolean batchOperations) {
original.batchOperations(batchOperations);
}
@Override
public void setDatabaseBridgeMode(DatabaseBridgeMode mode) {
original.setDatabaseBridgeMode(mode);
}
@Override
public DatabaseBridgeMode getDatabaseBridgeMode() {
return original.getDatabaseBridgeMode();
}
}
Practical Example: Player Stats System
public class PlayerStatsManager {
private final DatabaseBridge databaseBridge;
private final Map<UUID, PlayerStats> cachedStats;
public PlayerStatsManager(SuperiorSkyblock plugin) {
this.databaseBridge = plugin.getFactory().createPlayersDatabaseBridge(null, null);
this.cachedStats = new HashMap<>();
loadAllStats();
}
private void loadAllStats() {
// Set to IDLE mode during loading
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.IDLE);
databaseBridge.loadAllObjects("player_stats", result -> {
UUID uuid = UUID.fromString((String) result.get("uuid"));
int kills = (int) result.get("kills");
int deaths = (int) result.get("deaths");
int blocksPlaced = (int) result.get("blocks_placed");
PlayerStats stats = new PlayerStats(uuid, kills, deaths, blocksPlaced);
cachedStats.put(uuid, stats);
});
// Enable saving after loading
databaseBridge.setDatabaseBridgeMode(DatabaseBridgeMode.SAVE_DATA);
}
public void incrementKills(UUID playerId) {
PlayerStats stats = cachedStats.computeIfAbsent(playerId, PlayerStats::new);
stats.incrementKills();
// Save to database
DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
databaseBridge.updateObject(
"player_stats",
filter,
new Pair<>("kills", stats.getKills())
);
}
public void createPlayerStats(UUID playerId) {
PlayerStats stats = new PlayerStats(playerId, 0, 0, 0);
cachedStats.put(playerId, stats);
databaseBridge.insertObject(
"player_stats",
new Pair<>("uuid", playerId.toString()),
new Pair<>("kills", 0),
new Pair<>("deaths", 0),
new Pair<>("blocks_placed", 0)
);
}
public void deletePlayerStats(UUID playerId) {
cachedStats.remove(playerId);
DatabaseFilter filter = DatabaseFilter.fromFilter("uuid", playerId.toString());
databaseBridge.deleteObject("player_stats", filter);
}
public PlayerStats getStats(UUID playerId) {
return cachedStats.get(playerId);
}
}
Factory Methods
Use factory methods to create specialized database bridges:
SuperiorSkyblock plugin = ...; // Get plugin instance
DatabaseBridgeFactory factory = plugin.getFactory();
// Island database bridge
Island island = ...;
DatabaseBridge islandBridge = factory.createIslandsDatabaseBridge(island, null);
// Player database bridge
SuperiorPlayer player = ...;
DatabaseBridge playerBridge = factory.createPlayersDatabaseBridge(player, null);
// Grid database bridge
GridManager grid = plugin.getGrid();
DatabaseBridge gridBridge = factory.createGridDatabaseBridge(grid, null);
// Stacked blocks database bridge
StackedBlocksManager stackedBlocks = plugin.getStackedBlocks();
DatabaseBridge stackedBridge = factory.createStackedBlocksDatabaseBridge(stackedBlocks, null);
Best Practices
- Use
IDLE mode when loading data to prevent write operations
- Enable
SAVE_DATA mode only when ready to persist changes
- Use batch operations for bulk inserts/updates
- Always disable batch mode after operations complete
- Cache frequently accessed data to minimize database queries
- Use database filters for precise queries
- Handle null results when loading data
- Clean up resources in module’s
onDisable() method
- Use appropriate data types for column values
- Create indexes on frequently queried columns