Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.xreatlabs.space/llms.txt

Use this file to discover all available pages before exploring further.

Database API

NexAuth provides a database abstraction layer supporting multiple database backends with a unified API.

Supported Databases

MySQL/MariaDB

Production-ready with excellent performance.

PostgreSQL

Advanced features and great scalability.

H2

Testing and development only.

Database Interface

Basic Operations

DatabaseManager dbManager = NexAuthAPI.getInstance().getDatabaseManager();

// Execute query
dbManager.executeQuery("SELECT * FROM players WHERE username = ?", (resultSet) -> {
    while (resultSet.next()) {
        String username = resultSet.getString("username");
        // Process results
    }
}, username);

// Execute update
int affected = dbManager.executeUpdate(
    "UPDATE players SET last_login = ? WHERE username = ?",
    System.currentTimeMillis(), username
);

// Execute batch
dbManager.executeBatch((batch) -> {
    batch.addStatement("INSERT INTO players (...) VALUES (...)");
    batch.addStatement("UPDATE players SET ...");
});

Player Account Operations

// Load account
Optional<PlayerAccount> account = dbManager.loadAccount(username);

if (account.isPresent()) {
    // Access account data
    UUID uuid = account.get().getUUID();
    long registeredAt = account.get().getRegisteredAt();
}

// Save account
dbManager.saveAccount(account);

// Delete account
dbManager.deleteAccount(username);

// Check account exists
boolean exists = dbManager.accountExists(username);

Session Operations

// Create session
Session session = new Session(player, Duration.ofHours(24));
dbManager.saveSession(session);

// Load session
Optional<Session> session = dbManager.loadSession(sessionId);

// Update session
session.setLastActive(System.currentTimeMillis());
dbManager.updateSession(session);

// Delete session
dbManager.deleteSession(sessionId);

// Clean expired sessions
int cleaned = dbManager.cleanExpiredSessions();

Custom Tables

Creating Custom Tables

// Create custom table
dbManager.executeUpdate("""
    CREATE TABLE IF NOT EXISTS custom_player_data (
        id INT AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(16) NOT NULL,
        data_key VARCHAR(64) NOT NULL,
        data_value TEXT,
        created_at BIGINT NOT NULL,
        INDEX idx_username (username),
        INDEX idx_data_key (data_key)
    )
""");

Custom Queries

// Insert custom data
dbManager.executeUpdate(
    "INSERT INTO custom_player_data (username, data_key, data_value, created_at) VALUES (?, ?, ?, ?)",
    username, "custom_key", "custom_value", System.currentTimeMillis()
);

// Query custom data
dbManager.executeQuery(
    "SELECT * FROM custom_player_data WHERE username = ?",
    (resultSet) -> {
        while (resultSet.next()) {
            String key = resultSet.getString("data_key");
            String value = resultSet.getString("data_value");
            // Process data
        }
    },
    username
);

Transactions

Transaction Management

// Execute transaction
dbManager.executeTransaction(() -> {
    // Multiple related operations
    dbManager.saveAccount(account);
    dbManager.saveSession(session);
    dbManager.executeUpdate("INSERT INTO logs (...) VALUES (...)");
    
    // All operations will be committed or rolled back together
});

Transaction with Result

// Transaction with return value
boolean success = dbManager.executeTransactionWithResult(() -> {
    dbManager.saveAccount(account);
    dbManager.saveSession(session);
    return true; // Return result
});

Async Operations

Async Database Calls

// Async query
CompletableFuture<List<PlayerAccount>> future = dbManager
    .executeQueryAsync(
        "SELECT * FROM players WHERE last_login > ?",
        (resultSet) -> {
            List<PlayerAccount> accounts = new ArrayList<>();
            while (resultSet.next()) {
                accounts.add(mapToAccount(resultSet));
            }
            return accounts;
        },
        timestamp
    );

// Handle result
future.thenAccept(accounts -> {
    // Process accounts
}).exceptionally(throwable -> {
    // Handle error
    logger.error("Database error", throwable);
    return null;
});

Batch Async Operations

// Async batch operation
List<CompletableFuture<Void>> futures = new ArrayList<>();

for (PlayerAccount account : accounts) {
    CompletableFuture<Void> future = dbManager
        .saveAccountAsync(account)
        .thenAccept(saved -> {
            // Account saved
        });
    
    futures.add(future);
}

// Wait for all to complete
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    .thenAccept(v -> {
        logger.info("All accounts saved");
    });

Connection Pooling

Pool Configuration

database {
    type=nexauth-mysql
    properties {
        mysql {
            host="localhost"
            port=3306
            database="nexauth"
            user="nexauth"
            password="yourpassword"
            max-life-time=600000
        }
    }
    transient-retries=3
    transient-retry-delay-ms=250
}

Programmatic Configuration

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/nexauth");
config.setUsername("nexauth");
config.setPassword("password");
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
config.setMaxLifetime(1800000);

HikariDataSource dataSource = new HikariDataSource(config);
DatabaseManager dbManager = new DatabaseManager(dataSource);

Database Migration

Schema Migration

// Create migration
public class AddLastLoginColumn implements Migration {
    @Override
    public String getName() {
        return "add_last_login_column";
    }
    
    @Override
    public void up(DatabaseManager db) {
        db.executeUpdate("ALTER TABLE players ADD COLUMN last_login BIGINT");
    }
    
    @Override
    public void down(DatabaseManager db) {
        db.executeUpdate("ALTER TABLE players DROP COLUMN last_login");
    }
}

// Register migration
dbManager.registerMigration(new AddLastLoginColumn());

// Run migrations
dbManager.runMigrations();

Migration System

// Check migration status
MigrationStatus status = dbManager.getMigrationStatus();

// Run pending migrations
if (status.hasPendingMigrations()) {
    dbManager.runMigrations();
}

// Rollback migration
dbManager.rollbackMigration("add_last_login_column");

Performance Optimization

Query Optimization

// Use prepared statements
dbManager.executeQuery(
    "SELECT * FROM players WHERE username = ? AND uuid = ?",
    resultSet -> { /* process */ },
    username, uuid
);

// Use indexes in schema
dbManager.executeUpdate(
    "CREATE INDEX idx_username ON players(username)"
);

// Limit result sets
dbManager.executeQuery(
    "SELECT * FROM players LIMIT 100",
    resultSet -> { /* process */ }
);

Caching Strategy

// Cache frequently accessed data
LoadingCache<String, PlayerAccount> cache = Caffeine.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(5, TimeUnit.MINUTES)
    .build(key -> {
        return dbManager.loadAccount(key).orElse(null);
    });

// Use cache
PlayerAccount account = cache.get(username);

Error Handling

Database Exceptions

try {
    dbManager.executeUpdate("INSERT INTO players (...) VALUES (...)");
} catch (DatabaseException e) {
    if (e.isDuplicateKey()) {
        // Handle duplicate key
    } else if (e.isConnectionError()) {
        // Handle connection error
    } else {
        // Handle other errors
        logger.error("Database error", e);
    }
}

Retry Logic

// Retry with exponential backoff
int maxRetries = 3;
int retryCount = 0;
boolean success = false;

while (retryCount < maxRetries && !success) {
    try {
        dbManager.executeUpdate("INSERT INTO players (...) VALUES (...)");
        success = true;
    } catch (DatabaseException e) {
        retryCount++;
        if (retryCount < maxRetries) {
            Thread.sleep(1000L * retryCount); // Exponential backoff
        } else {
            throw e;
        }
    }
}

Best Practices

Next Steps

Crypto API

Cryptography utilities for secure data handling.