0Pricing
Scala for Backend Engineering & Functional Programming · Leçon

Exécuter des requêtes

Lisez les lignes dans des classes de cas.

Exécuter des requêtes est une leçon Scala for Backend Engineering & Functional Programming gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Scala for Backend Engineering & Functional Programming, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.

L'interpolateur sql

L'interpolateur de chaînes sql de Doobie est au cœur des requêtes. Il analyse votre SQL et transforme les valeurs Scala intégrées en paramètres liés de manière sûre.

Les valeurs interpolées deviennent des paramètres fictifs JDBC ? ; il n'y a donc ni injection SQL ni liaison manuelle de PreparedStatement.

import doobie.implicits._

val minAge = 18
val frag = sql"select name from users where age >= $minAge"

Du fragment à la requête

Une expression sql"..." est un Fragment. Pour l'exécuter comme une lecture, vous appelez .query[A] en choisissant le type de ligne A.

Doobie utilise une classe de types Read[A] pour mapper les colonnes de résultat vers A, et prend en charge les types primitifs, les tuples et les classes case.

case class User(name: String, age: Int)

val q: Query0[User] =
  sql"select name, age from users".query[User]

unique, option et to

Un Query0[A] propose différents accumulateurs. .unique attend exactement une ligne, .option en attend zéro ou une, et .to[List] collecte toutes les lignes.

Chacun renvoie un ConnectionIO que vous exécutez ensuite avec .transact.

val one: ConnectionIO[User] = q.unique
val maybe: ConnectionIO[Option[User]] = q.option
val all: ConnectionIO[List[User]] = q.to[List]

Mapper les lignes vers des classes case

Doobie dérive automatiquement les instances Read pour les classes case lorsque chaque champ possède un mappage de colonne. L'ordre des colonnes doit correspondre à celui de la liste select.

Vous pouvez ainsi sélectionner directement des types métier riches sans écrire de code répétitif pour analyser les lignes.

case class Account(id: Long, email: String, active: Boolean)

val accounts =
  sql"select id, email, active from accounts"
    .query[Account].to[Vector]

Requêtes paramétrées

Chaque valeur Scala interpolée est liée comme paramètre à l'aide de son instance Put. Vous pouvez en interpoler autant que nécessaire, y compris à des positions différentes.

Comme elles sont liées et non concaténées, les types sont vérifiés et l'injection est impossible.

def findByEmail(email: String): ConnectionIO[Option[Account]] =
  sql"select id, email, active from accounts where email = $email"
    .query[Account].option

Flux de résultats volumineux

Pour les grands ensembles de résultats, utilisez .stream afin d'obtenir un Stream[ConnectionIO, A] fs2. Les lignes sont récupérées paresseusement à l'aide d'un curseur côté serveur, ce qui maintient une consommation mémoire limitée.

Combinez-le avec les combinateurs fs2 pour traiter progressivement des millions de lignes.

import fs2.Stream

val s: Stream[ConnectionIO, Account] =
  sql"select id, email, active from accounts"
    .query[Account].stream

Contrôle de la taille de récupération

La taille de récupération par défaut du curseur peut tout charger en une seule fois avec certains pilotes. .streamWithChunkSize(n) définit la taille de récupération JDBC afin que le curseur récupère n lignes par aller-retour.

Le réglage de cette valeur équilibre le nombre d'allers-retours et la mémoire utilisée.

val s =
  sql"select id, email, active from accounts"
    .query[Account]
    .streamWithChunkSize(512)

Colonnes facultatives et nullabilité

Les colonnes pouvant être NULL sont mappées vers Option[A] dans votre type de ligne. Si une colonne peut être NULL, vous devez la lire comme une Option, sinon Doobie lève une erreur lorsqu'elle rencontre une valeur nulle.

La nullabilité est ainsi explicite et sûre du point de vue du typage à la frontière du système.

case class Person(id: Long, nickname: Option[String])

val ps =
  sql"select id, nickname from people".query[Person].to[List]

Construction de SQL avec des fragments

Les valeurs Fragment se composent avec ++, ce qui vous permet d'assembler des requêtes à partir de morceaux tout en conservant les paramètres liés.

L'interpolateur fr construit un fragment auquel il ajoute un espace final, ce qui est pratique pour assembler des clauses.

val base = fr"select id, email, active from accounts"
val where = fr"where active = $${true}"
val q = (base ++ where).query[Account]

Clauses WHERE dynamiques

Les utilitaires Fragments de Doobie construisent des clauses conditionnelles. Fragments.whereAndOpt combine les filtres facultatifs et n'émet que ceux qui sont présents.

C'est la manière idiomatique de construire des requêtes de recherche dynamiques sûres.

import doobie.util.fragments._

val emailOpt: Option[String] = Some("a@b.com")
val filter = whereAndOpt(emailOpt.map(e => fr"email = $e"))
val q = (fr"select id, email, active from accounts" ++ filter)

Vérification des requêtes à la compilation

L'analyse check de Doobie exécute une requête sur le schéma de la base afin de vérifier que les types et le nombre de colonnes correspondent à vos types Scala.

Utilisée dans les tests, elle détecte les dérives du schéma avant leur arrivée en production.

import doobie.scalatest._

// inside a spec mixing in IOChecker
check(sql"select id, email, active from accounts".query[Account])

Vérification rapide

Choisissez le bon accumulateur.

Récapitulatif

L'interpolateur sql construit des Fragments paramétrés ; .query[A] les transforme en Query0[A] mappé via Read[A].

Choisissez .unique, .option, .to[List] ou .stream pour accumuler les lignes. Utilisez Fragments pour les clauses dynamiques et check pour valider la requête par rapport au schéma.

Questions Fréquemment Posées

La leçon « Exécuter des requêtes » est-elle gratuite ?

Oui — le texte complet de « Exécuter des requêtes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Scala for Backend Engineering & Functional Programming, passe à CoddyKit PRO. Le cours Scala for Backend Engineering & Functional Programming comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Exécuter des requêtes » ?

Lisez les lignes dans des classes de cas. Tu pratiques Scala for Backend Engineering & Functional Programming avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Scala for Backend Engineering & Functional Programming ?

Aucune expérience préalable n'est requise. Scala for Backend Engineering & Functional Programming sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Exécuter des requêtes » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Scala for Backend Engineering & Functional Programming ?

Oui. Chaque leçon Scala for Backend Engineering & Functional Programming inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Se connecter avec un transacteur
  2. Exécuter des requêtes
  3. Insertions et mises à jour
  4. Composer des transactions
← Retour à Scala for Backend Engineering & Functional Programming