Queries
Sarah provides a fluent API for executing database queries through the RequestHelper class. This guide covers all query operations with practical examples.
RequestHelper
The RequestHelper is your main interface for database operations:
RequestHelper requestHelper = new RequestHelper(databaseConnection, logger);
SELECT Queries
Select All Records
// Select all players
List<PlayerDTO> players = requestHelper.selectAll("players", PlayerDTO.class);
Select with Conditions
// Select players with more than 1000 play time
List<PlayerDTO> activePlayers = requestHelper.select("players", PlayerDTO.class, table -> {
table.where("play_time", ">", 1000);
});
Select with Multiple Conditions
List<PlayerDTO> results = requestHelper.select("players", PlayerDTO.class, table -> {
table.where("play_time", ">", 1000);
table.where("is_banned", false);
table.whereNotNull("last_login");
});
Select with Ordering
List<PlayerDTO> topPlayers = requestHelper.select("players", PlayerDTO.class, table -> {
table.where("is_banned", false);
table.orderByDesc("play_time");
});
Select with IN Clause
List<String> names = Arrays.asList("Steve", "Alex", "Notch");
List<PlayerDTO> players = requestHelper.select("players", PlayerDTO.class, table -> {
table.whereIn("name", names);
});
Select as Raw Maps
When you don't have a DTO class:
List<Map<String, Object>> results = requestHelper.select("players", table -> {
table.where("is_online", true);
});
for (Map<String, Object> row : results) {
String name = (String) row.get("name");
long playTime = (long) row.get("play_time");
}
Count Records
long totalPlayers = requestHelper.count("players", table -> {});
long activePlayers = requestHelper.count("players", table -> {
table.where("play_time", ">", 1000);
});
INSERT Queries
Basic Insert
requestHelper.insert("players", schema -> {
schema.uuid("uuid", playerUuid);
schema.string("name", playerName);
schema.bigInt("play_time", 0);
});
Insert from DTO
// Your DTO class
public record PlayerDTO(UUID uuid, String name, long playTime) {}
// Insert
PlayerDTO player = new PlayerDTO(uuid, "Steve", 0);
requestHelper.insert("players", PlayerDTO.class, player);
Insert with Result Callback
Get the auto-generated ID:
requestHelper.insert("homes", schema -> {
schema.uuid("player_uuid", playerUuid);
schema.string("name", "MyHome");
schema.string("world", "world");
schema.decimal("x", x);
schema.decimal("y", y);
schema.decimal("z", z);
}, generatedId -> {
System.out.println("Created home with ID: " + generatedId);
});
Insert with Error Handling
requestHelper.insert("players", schema -> {
schema.uuid("uuid", playerUuid);
schema.string("name", playerName);
}, generatedId -> {
logger.info("Player created with ID: " + generatedId);
}, () -> {
logger.warning("Failed to create player!");
});
Batch Insert
List<PlayerDTO> players = Arrays.asList(
new PlayerDTO(uuid1, "Steve", 0),
new PlayerDTO(uuid2, "Alex", 0),
new PlayerDTO(uuid3, "Notch", 0)
);
requestHelper.insertMultiple("players", PlayerDTO.class, players);
UPDATE Queries
Basic Update
requestHelper.update("players", schema -> {
schema.bigInt("play_time", newPlayTime);
schema.where("uuid", playerUuid);
});
Update Multiple Columns
requestHelper.update("players", schema -> {
schema.string("name", newName);
schema.bigInt("play_time", newPlayTime);
schema.bool("is_online", true);
schema.where("uuid", playerUuid);
});
Batch Update
List<Schema> updates = new ArrayList<>();
for (PlayerDTO player : playersToUpdate) {
Schema schema = SchemaBuilder.update("players", s -> {
s.bigInt("play_time", player.playTime());
s.where("uuid", player.uuid());
});
updates.add(schema);
}
requestHelper.updateMultiple(updates);
UPSERT Queries (Insert or Update)
Upsert inserts a new row or updates if the primary key already exists.
Basic Upsert
requestHelper.upsert("players", schema -> {
schema.uuid("uuid", playerUuid).primary();
schema.string("name", playerName);
schema.bigInt("play_time", playTime);
});
SQLite Requirement
For SQLite, you must mark the primary key column with .primary():
schema.uuid("uuid", playerUuid).primary(); // Required for SQLite!
Upsert from DTO
PlayerDTO player = new PlayerDTO(uuid, "Steve", 1000);
requestHelper.upsert("players", PlayerDTO.class, player);
Batch Upsert
List<PlayerDTO> players = getPlayersToSave();
requestHelper.upsertMultiple("players", PlayerDTO.class, players);
DELETE Queries
Delete with Condition
requestHelper.delete("players", schema -> {
schema.where("uuid", playerUuid);
});
Delete with Multiple Conditions
requestHelper.delete("sessions", schema -> {
schema.where("player_uuid", playerUuid);
schema.where("is_expired", true);
});
Delete Old Records
requestHelper.delete("logs", schema -> {
schema.where("created_at", "<", thirtyDaysAgo);
});
WHERE Conditions
Equality
schema.where("name", "Steve");
schema.where("uuid", playerUuid); // UUID support
Comparison Operators
schema.where("play_time", ">", 1000);
schema.where("balance", ">=", 100.0);
schema.where("level", "<", 10);
schema.where("score", "<=", 50);
schema.where("name", "!=", "Admin");
NULL Checks
schema.whereNull("deleted_at");
schema.whereNotNull("verified_at");
IN Clause
schema.whereIn("status", "active", "pending", "review");
schema.whereIn("name", Arrays.asList("Steve", "Alex"));
Combining Conditions
All conditions are combined with AND:
requestHelper.select("players", PlayerDTO.class, table -> {
table.where("is_banned", false);
table.where("play_time", ">", 100);
table.whereNotNull("last_login");
table.whereIn("rank", "vip", "mvp", "admin");
});
// WHERE is_banned = 0 AND play_time > 100 AND last_login IS NOT NULL AND rank IN ('vip', 'mvp', 'admin')
Data Transfer Objects (DTOs)
Sarah automatically maps query results to Java objects.
Using Records (Java 14+)
public record PlayerDTO(
UUID uuid,
String name,
long playTime,
boolean isBanned
) {}
// Sarah will automatically map columns to constructor parameters
List<PlayerDTO> players = requestHelper.selectAll("players", PlayerDTO.class);
Using Classes with @Column Annotation
For older Java versions or custom column names:
public class PlayerDTO {
@Column("uuid")
private UUID uuid;
@Column("name")
private String name;
@Column("play_time")
private long playTime;
@Column("is_banned")
private boolean banned;
// Constructor matching column order
public PlayerDTO(UUID uuid, String name, long playTime, boolean banned) {
this.uuid = uuid;
this.name = name;
this.playTime = playTime;
this.banned = banned;
}
// Getters...
}
Column Name Mapping
Sarah converts between Java camelCase and SQL snake_case:
| Java Field | Database Column |
|---|---|
playTime | play_time |
isBanned | is_banned |
lastLoginAt | last_login_at |
uuid | uuid |
Complete Examples
Player Statistics System
public class PlayerStatsManager {
private final RequestHelper requestHelper;
public PlayerStatsManager(RequestHelper requestHelper) {
this.requestHelper = requestHelper;
}
public void saveStats(UUID uuid, PlayerStats stats) {
requestHelper.upsert("player_stats", schema -> {
schema.uuid("uuid", uuid).primary();
schema.bigInt("kills", stats.getKills());
schema.bigInt("deaths", stats.getDeaths());
schema.bigInt("play_time", stats.getPlayTime());
schema.decimal("balance", stats.getBalance());
});
}
public PlayerStats getStats(UUID uuid) {
List<PlayerStats> results = requestHelper.select("player_stats", PlayerStats.class, table -> {
table.where("uuid", uuid);
});
return results.isEmpty() ? new PlayerStats() : results.get(0);
}
public List<PlayerStats> getTopPlayers(int limit) {
return requestHelper.select("player_stats", PlayerStats.class, table -> {
table.orderByDesc("kills");
// Note: LIMIT is applied after query for now
}).stream().limit(limit).toList();
}
}
Home System
public class HomeManager {
private final RequestHelper requestHelper;
public void createHome(UUID playerUuid, String name, Location location) {
requestHelper.insert("homes", schema -> {
schema.uuid("player_uuid", playerUuid);
schema.string("name", name);
schema.string("world", location.getWorld().getName());
schema.decimal("x", location.getX());
schema.decimal("y", location.getY());
schema.decimal("z", location.getZ());
schema.decimal("yaw", location.getYaw());
schema.decimal("pitch", location.getPitch());
});
}
public List<HomeDTO> getHomes(UUID playerUuid) {
return requestHelper.select("homes", HomeDTO.class, table -> {
table.where("player_uuid", playerUuid);
});
}
public void deleteHome(UUID playerUuid, String name) {
requestHelper.delete("homes", schema -> {
schema.where("player_uuid", playerUuid);
schema.where("name", name);
});
}
public long countHomes(UUID playerUuid) {
return requestHelper.count("homes", table -> {
table.where("player_uuid", playerUuid);
});
}
}
Next Steps
- Schema Builder reference - Complete API documentation
- Migrations - Manage database schema