Référence du Schema Builder
Ceci est la référence complète de l'API du Schema Builder de Sarah. Utilisez les méthodes de colonnes et leurs modificateurs dans les migrations ; les conditions et options SELECT s’appliquent aux requêtes.
Types de Colonnes
Les types suivent le dialecte configuré. PostgreSQL adapte également les types SQL bruts DOUBLE en DOUBLE PRECISION, DATETIME en TIMESTAMP et TINYINT en SMALLINT.
uuid
Crée une colonne VARCHAR(36) pour un UUID, y compris sur PostgreSQL.
// Définition seule
table.uuid("player_id");
// Avec valeur
table.uuid("player_id", playerUuid);string
Crée une colonne VARCHAR.
// Définition avec longueur
table.string("name", 64);
// Avec valeur
table.string("name", playerName);text
Crée une colonne TEXT pour les chaînes plus longues.
table.text("description");longText
Crée une colonne LONGTEXT pour les contenus très longs, ou TEXT sur PostgreSQL.
table.longText("content");integer
Crée une colonne INT.
table.integer("count");bigInt
Crée une colonne BIGINT.
// Définition seule
table.bigInt("balance");
// Avec valeur
table.bigInt("balance", 1000L);decimal
Crée une colonne DECIMAL.
// Précision par défaut
table.decimal("price");
// Précision personnalisée (10 chiffres au total, 2 après la virgule)
table.decimal("price", 10, 2);
// Avec valeur
table.decimal("price", 99.99);bool
Crée une colonne BOOLEAN, notamment sur PostgreSQL.
// Définition seule
table.bool("is_active");
// Avec valeur
table.bool("is_active", true);json
Crée une colonne JSON.
table.json("metadata");blob
Crée une colonne BLOB pour les données binaires, ou BYTEA sur PostgreSQL.
// Définition seule
table.blob("data");
// Avec tableau d'octets
table.blob("data", byteArray);
// Avec objet (auto-sérialisé)
table.blob("data", myObject);date
Crée une colonne DATE.
table.date("birth_date", new Date());timestamp
Crée une colonne TIMESTAMP.
table.timestamp("verified_at");enumValue
Stocke le nom d’une constante Java dans une colonne VARCHAR(255).
table.enumValue("status");
table.enumValue("status", PlayerStatus.ACTIVE);enumType
Crée un ENUM natif sur MySQL/MariaDB, TEXT sur SQLite et VARCHAR(255) sur PostgreSQL. Les types de remplacement ne limitent pas les valeurs autorisées.
table.enumType("status", "ACTIVE", "BANNED");
table.enumType("status", PlayerStatus.class);object
Stocke n'importe quel objet (sérialisé).
table.object("settings", settingsObject);Auto Incrémentation
autoIncrement
Crée une clé primaire INT auto-incrémentée. PostgreSQL utilise INTEGER GENERATED BY DEFAULT AS IDENTITY.
table.autoIncrement("id");autoIncrementBigInt
Crée une clé primaire BIGINT auto-incrémentée. PostgreSQL utilise BIGINT GENERATED BY DEFAULT AS IDENTITY.
table.autoIncrementBigInt("id");Modificateurs de Colonnes
primary
Marque la colonne comme clé primaire.
table.uuid("uuid").primary();nullable
Autorise les valeurs NULL.
table.string("nickname", 32).nullable();unique
Ajoute une contrainte UNIQUE.
table.string("email", 255).unique();
// Ou avec booléen explicite
table.string("email", 255).unique(true);defaultValue
Définit une valeur par défaut.
table.bigInt("balance").defaultValue(0);
table.string("status", 16).defaultValue("pending");
table.bool("active").defaultValue(true);defaultCurrentTimestamp
Définit la valeur par défaut à CURRENT_TIMESTAMP.
table.timestamp("created_at").defaultCurrentTimestamp();foreignKey
Crée une relation de clé étrangère.
// Basique (référence la colonne 'id')
table.uuid("user_id").foreignKey("users");
// Avec colonne personnalisée et suppression en cascade
table.uuid("user_id").foreignKey("users", "uuid", true);increment
Ajoute une valeur à une colonne numérique dans une écriture atomique. Un montant négatif soustrait. En INSERT, le montant est inséré tel quel ; en UPSERT, il est inséré pour une nouvelle ligne ou ajouté à la valeur existante.
requestHelper.update("players", table -> {
table.increment("balance", 10);
table.where("uuid", playerUuid);
});expression
Affecte une expression SQL avec des paramètres liés. Utilisez les accents graves pour les noms de colonnes, traduits selon le dialecte. En UPSERT, l’expression s’applique seulement au conflit ; la colonne est omise pour une nouvelle ligne et doit donc accepter son absence.
requestHelper.update("players", table -> {
table.expression("balance", "`balance` + ?", 10);
table.expression("updated_at", "CURRENT_TIMESTAMP");
table.where("uuid", playerUuid);
});insertOnly
Marque la dernière valeur ajoutée : un UPSERT l’insère pour une nouvelle ligne et conserve la valeur existante en cas de conflit. Un UPSERT dont toutes les colonnes sont insert-only ne modifie rien au conflit.
requestHelper.upsert("players", table -> {
table.uuid("uuid", playerUuid).primary();
table.date("created_at", new Date()).insertOnly();
table.increment("play_time", 60);
});Aides pour les Timestamps
timestamps
Ajoute les colonnes created_at et updated_at.
table.timestamps();Sur PostgreSQL, updated_at a une valeur par défaut CURRENT_TIMESTAMP mais ne change pas automatiquement lors d’un UPDATE. Affectez-le explicitement dans vos requêtes. Le dialecte est déterminé à l’exécution ; MigrationManager.setDatabaseConfiguration() n’est pas nécessaire pour ces méthodes.
createdAt
Ajoute seulement la colonne created_at.
table.createdAt();updatedAt
Ajoute seulement la colonne updated_at, avec le comportement du moteur décrit ci-dessus pour timestamps().
table.updatedAt();Conditions WHERE
where
Égalité ou comparaison basique.
// Égalité
table.where("name", "Steve");
table.where("uuid", playerUuid);
// Comparaison
table.where("balance", ">", 1000);
table.where("level", ">=", 10);
table.where("score", "<", 50);
table.where("rank", "<=", 100);
table.where("status", "!=", "banned");whereNull
Vérifie les valeurs NULL.
table.whereNull("deleted_at");whereNotNull
Vérifie les valeurs non-NULL.
table.whereNotNull("verified_at");whereIn
Vérifie si la valeur est dans une liste. Une liste vide ne correspond à aucune ligne. PostgreSQL lie les valeurs numériques avec leur type.
// Varargs
table.whereIn("status", "active", "pending", "review");
// Liste
table.whereIn("name", Arrays.asList("Steve", "Alex"));
// Avec préfixe de table
table.whereIn("users", "status", statusList);whereNotIn
Exclut les valeurs indiquées. Sans valeur, toutes les lignes correspondent. La variante avec préfixe accepte une liste.
table.whereNotIn("status", "banned", "deleted");
table.whereNotIn("users", "name", Arrays.asList("Bot", "Test"));whereBetween
Sélectionne les valeurs comprises entre deux bornes incluses. Les paramètres conservent leur type.
table.whereBetween("level", 10, 20);whereNotBetween
Exclut l’intervalle, bornes comprises.
table.whereNotBetween("level", 10, 20);whereLike
Recherche un motif SQL LIKE : % correspond à une suite de caractères et _ à un caractère.
table.whereLike("name", "Alex%");whereNotLike
Exclut les valeurs correspondant au motif LIKE.
table.whereNotLike("name", "Bot%");orWhere
Relie une condition à la précédente avec OR. Les autres appels WHERE utilisent AND. AND est prioritaire sur OR ; utilisez un groupe pour changer cette priorité.
table.where("status", "active").orWhere("status", "pending");
table.orWhere("balance", ">", 1000);
table.orWhere("users", "level", ">=", 10);orWhereNull
Ajoute une condition OR vérifiant NULL.
table.where("status", "pending").orWhereNull("verified_at");orWhereNotNull
Ajoute une condition OR vérifiant une valeur non-NULL.
table.where("status", "active").orWhereNotNull("verified_at");orWhereIn
Ajoute une condition OR avec une liste de valeurs.
table.where("is_premium", true).orWhereIn("rank", "vip", "admin");orWhereBetween
Ajoute une condition OR avec deux bornes incluses.
table.where("is_premium", true).orWhereBetween("level", 10, 20);where / orWhere (groupes)
Place les conditions du callback entre parenthèses. where(group) les relie avec AND, orWhere(group) avec OR. Un groupe vide n’ajoute aucune condition.
table.where("active", true);
table.where(group -> group.where("rank", "vip").orWhere("rank", "admin"));
table.orWhere(group -> group.where("level", ">=", 50).whereNotNull("verified_at"));Opérations JOIN
leftJoin
table.leftJoin(
"users", // Table primaire
"u", // Alias
"uuid", // Colonne primaire
"orders", // Table étrangère
"user_uuid" // Colonne étrangère
);rightJoin
table.rightJoin("users", "u", "uuid", "orders", "user_uuid");innerJoin
table.innerJoin("users", "u", "uuid", "orders", "user_uuid");fullJoin
table.fullJoin("users", "u", "uuid", "orders", "user_uuid");Join avec Condition Supplémentaire
JoinCondition condition = JoinCondition.and("u", "status", "active");
table.leftJoin("users", "u", "uuid", "orders", "user_uuid", condition);La condition supplémentaire compare u.status à la chaîne active. Sarah échappe cette valeur selon le moteur, y compris les antislashs sur MySQL/MariaDB. Pour générer vous-même le SQL d'un JoinCondition complet, utilisez getJoinClause(config.getDialect()) afin d'appliquer l'échappement du moteur.
Options SELECT
addSelect
Spécifier les colonnes à sélectionner. Les alias sont disponibles comme clés dans les maps de résultats, y compris sur MySQL.
table.addSelect("name");
table.addSelect("users", "name"); // Avec préfixe de table
table.addSelect("users", "name", "userName"); // Avec alias
table.addSelect("users", "name", "userName", "Unknown"); // Avec défautdistinct
Sélectionner seulement les lignes distinctes.
table.distinct();orderBy
Trier les résultats par ordre croissant.
table.orderBy("name");orderByDesc
Trier les résultats par ordre décroissant.
table.orderByDesc("created_at");limit
Limite le nombre de lignes retournées par une sélection.
table.limit(20);offset
Ignore les premières lignes d’une sélection. S’utilise avec un tri et une limite pour la pagination ; peut aussi être utilisé seul.
table.orderBy("name");
table.limit(20);
table.offset(40);groupBy
Regroupe les résultats sur une ou plusieurs colonnes. Sélectionnez uniquement les colonnes groupées ou des agrégations.
table.addSelect("rank");
table.groupBy("rank");having
Filtre les groupes à partir d’une expression SQL et d’une valeur liée. Plusieurs appels sont reliés avec AND. L’expression doit être fournie par le développeur.
table.addSelect("rank");
table.groupBy("rank");
table.having("COUNT(*)", ">=", 10);Types de Schema
Sarah utilise différents types de schema pour différentes opérations :
| Type | Description | Créé Par |
|---|---|---|
CREATE | Créer une nouvelle table | SchemaBuilder.create() |
ALTER | Modifier une table existante | SchemaBuilder.alter() |
DROP | Supprimer une table | SchemaBuilder.drop() |
RENAME | Renommer une table | SchemaBuilder.rename() |
INSERT | Insérer des données | SchemaBuilder.insert() |
UPSERT | Insérer ou mettre à jour | SchemaBuilder.upsert() |
UPDATE | Mettre à jour des données | SchemaBuilder.update() |
SELECT | Requêter des données | SchemaBuilder.select() |
SELECT_COUNT | Compter les lignes | SchemaBuilder.selectCount() |
DELETE | Supprimer des données | SchemaBuilder.delete() |
CREATE_INDEX | Créer un index | SchemaBuilder.createIndex() |
Méthodes Statiques du SchemaBuilder
create
Créer une nouvelle table.
Schema schema = SchemaBuilder.create(migration, "users", table -> {
table.uuid("uuid").primary();
table.string("name", 64);
});create (depuis template)
Créer une table depuis un template de classe.
Schema schema = SchemaBuilder.create(migration, "users", UserDTO.class);alter
Modifier une table existante.
Schema schema = SchemaBuilder.alter(migration, "users", table -> {
table.string("email", 255).nullable();
});drop
Supprimer une table.
Schema schema = SchemaBuilder.drop(migration, "old_table");rename
Renommer une table.
Schema schema = SchemaBuilder.rename(migration, "old_name", "new_name");createIndex
Créer un index.
Schema schema = SchemaBuilder.createIndex(migration, "users", "email");insert
Insérer des données.
Schema schema = SchemaBuilder.insert("users", table -> {
table.uuid("uuid", uuid);
table.string("name", name);
});upsert
Insérer ou mettre à jour des données.
Schema schema = SchemaBuilder.upsert("users", table -> {
table.uuid("uuid", uuid).primary();
table.string("name", name);
});update
Mettre à jour des données.
Schema schema = SchemaBuilder.update("users", table -> {
table.string("name", newName);
table.where("uuid", uuid);
});select
Requêter des données.
Schema schema = SchemaBuilder.select("users");selectCount
Compter les lignes.
Schema schema = SchemaBuilder.selectCount("users");delete
Supprimer des données.
Schema schema = SchemaBuilder.delete("users");Méthodes d'Exécution
execute
Exécuter l'opération du schema.
int affectedRows = schema.execute(databaseConnection, logger);executeSelect
Exécuter une requête SELECT.
List<Map<String, Object>> results = schema.executeSelect(databaseConnection, logger);executeSelect (avec mapping)
Exécuter SELECT et mapper vers des objets.
List<UserDTO> users = schema.executeSelect(UserDTO.class, databaseConnection, logger);executeSelectCount
Exécuter une requête COUNT.
long count = schema.executeSelectCount(databaseConnection, logger);Exemple Complet
public class UserRepository {
private final RequestHelper helper;
public UserRepository(RequestHelper helper) {
this.helper = helper;
}
public UserRepository(RequestHelper helper) {
this.helper = helper;
}
public void createUser(User user) {
helper.upsert("users", schema -> {
schema.uuid("uuid", user.getUuid()).primary();
schema.string("name", user.getName());
schema.string("email", user.getEmail()).unique();
schema.bigInt("balance", user.getBalance()).defaultValue(0);
schema.bool("is_premium", user.isPremium()).defaultValue(false);
schema.text("bio").nullable();
schema.json("settings");
schema.timestamps();
});
}
public List<User> findPremiumUsers() {
return helper.select("users", User.class, table -> {
table.where("is_premium", true);
table.whereNotNull("email");
table.orderByDesc("balance");
});
}
public List<User> searchUsers(String query) {
return helper.select("users", User.class, table -> {
table.where("name", "LIKE", "%" + query + "%");
});
}
public void deleteInactiveUsers(Date threshold) {
helper.delete("users", table -> {
table.where("last_login", "<", threshold);
table.where("is_premium", false);
});
}
}