Intégration de bases de données avec Slick/Doobie
Apprenez à intégrer des bases de données à votre application Play à l’aide d’ORM et de bibliothèques Scala populaires tels que Slick ou Doobie.
Intégration de bases de données avec Slick/Doobie est une leçon Scala for Backend Engineering & Functional Programming gratuite sur CoddyKit. Ceci est la leçon 3 sur 3. 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 3 leçons au total.
Pourquoi intégrer des bases de données ?
Les applications web doivent souvent stocker et récupérer des données de manière persistante. Il peut s’agir de profils utilisateur, d’informations sur des produits ou d’articles de blog.
- Persistance : les données restent disponibles même après le redémarrage de l’application.
- Évolutivité : gérer de grandes quantités de données et de nombreux utilisateurs simultanés.
- Fiabilité : garantir l’intégrité et la possibilité de récupérer les données.
L’intégration d’une base de données est essentielle pour toute application web dynamique créée avec Play Framework.
Slick et Doobie : outils de base de données de Scala
Scala propose de puissantes bibliothèques pour interagir avec les bases de données, dont Slick et Doobie, deux choix populaires.
- Slick : une bibliothèque de mappage relationnel fonctionnel (FRM). Elle vous permet de travailler avec des bases de données de manière fonctionnelle et avec une vérification des types, en masquant la complexité de SQL.
- Doobie : une couche JDBC purement fonctionnelle. Elle vous donne un contrôle direct sur les requêtes SQL tout en s’intégrant à des paradigmes de programmation fonctionnelle tels que Cats Effect.
Dans cette leçon, nous nous concentrerons sur Slick en raison de son abstraction de plus haut niveau, qui simplifie souvent l’intégration initiale avec Play Framework.
Configurer Slick dans Play
Commencez par ajouter Slick et un pilote de base de données à votre build.sbt. Nous utiliserons H2, une base de données en mémoire, pour faciliter la configuration.
Configurez ensuite la connexion à votre base de données dans conf/application.conf.
import play.sbt.PlayImport._
libraryDependencies ++= Seq(
jdbc,
ws,
"com.typesafe.play" %% "play-slick" % "5.0.0",
"com.typesafe.play" %% "play-slick-evolutions" % "5.0.0",
"com.h2database" % "h2" % "2.2.224"
)Configuration de la base de données
Ajoutez ces lignes à votre conf/application.conf pour configurer la base de données H2 et le profil Slick. slick.dbs.default.profile indique le type de base de données.
play.db.prototype.slick définit un modèle pour les connexions à la base de données.
slick.dbs.default.profile="slick.jdbc.H2Profile$"
play.db {
prototype.slick = {
db.driver="org.h2.Driver"
db.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
db.username="sa"
db.password=""
}
# Apply the prototype to our default DB
default = ${play.db.prototype.slick}
}Définir votre modèle (table Slick)
Dans Slick, vous représentez les tables de base de données sous forme de classes Scala qui étendent slick.jdbc.H2Profile.api.Table. Chaque colonne est associée à un type Scala.
Nous définissons un TableQuery pour chaque table, qui constitue le point d’entrée pour effectuer des requêtes.
import slick.jdbc.H2Profile.api._
// Define a case class for our data model
case class User(id: Option[Long], name: String, email: String)
// Define the table mapping
class Users(tag: Tag) extends Table[User](tag, "users") {
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def email = column[String]("email")
// Every table needs a * projection with the default mapping
def * = (id, name, email) <> (User.tupled, User.unapply)
}
// TableQuery for accessing the Users table
val users = TableQuery[Users]Code : création de la table et du schéma
Cet exemple exécutable montre comment définir une table User, puis créer son schéma dans une base de données H2 en mémoire. La méthode db.run exécute les opérations sur la base de données de manière asynchrone.
import slick.jdbc.H2Profile.api._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
case class User(id: Option[Long], name: String, email: String)
class Users(tag: Tag) extends Table[User](tag, "users") {
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def email = column[String]("email")
def * = (id, name, email) <> (User.tupled, User.unapply)
}
object SlickDemo {
val users = TableQuery[Users]
def main(args: Array[String]): Unit = {
val db = Database.forURL("jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
try {
val setup = DBIO.seq(
users.schema.create
)
val future = db.run(setup)
Await.result(future, 2.seconds)
println("Users table created successfully!")
} finally {
db.close()
}
}
}Le modèle DAO pour les opérations
Le modèle Data Access Object (DAO) permet d’encapsuler les opérations sur la base de données. Il sépare la logique métier de votre application de sa logique de persistance.
Un UserDAO contiendrait des méthodes permettant d’insérer, d’interroger, de mettre à jour et de supprimer des objets User.
import slick.jdbc.H2Profile.api._
import scala.concurrent.Future
class UserDAO(db: Database) {
import SlickDemo.users // Assuming users TableQuery is in SlickDemo object
def insert(user: User): Future[User] = {
db.run(users returning users.map(_.id) into ((user, id) => user.copy(id = id)) += user)
}
def findAll(): Future[Seq[User]] = {
db.run(users.result)
}
def findById(id: Long): Future[Option[User]] = {
db.run(users.filter(_.id === id).result.headOption)
}
}Code : insertion et interrogation des données
Voici comment insérer un nouvel utilisateur, puis interroger tous les utilisateurs de la base de données à l’aide des méthodes du DAO que nous venons de définir.
import slick.jdbc.H2Profile.api._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration._
case class User(id: Option[Long], name: String, email: String)
class Users(tag: Tag) extends Table[User](tag, "users") {
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def email = column[String]("email")
def * = (id, name, email) <> (User.tupled, User.unapply)
}
class UserDAO(db: Database) {
val users = TableQuery[Users]
def insert(user: User): Future[User] =
db.run(users returning users.map(_.id) into ((u, id) => u.copy(id = id)) += user)
def findAll(): Future[Seq[User]] =
db.run(users.result)
}
object SlickOperations {
def main(args: Array[String]): Unit = {
val db = Database.forURL("jdbc:h2:mem:test2;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
val userDAO = new UserDAO(db)
try {
Await.result(db.run(userDAO.users.schema.create), 2.seconds)
println("Table created.")
val future = for {
user1 <- userDAO.insert(User(None, "Alice", "alice@example.com"))
user2 <- userDAO.insert(User(None, "Bob", "bob@example.com"))
allUsers <- userDAO.findAll()
} yield allUsers
val result = Await.result(future, 5.seconds)
println(s"All users: $result")
} finally {
db.close()
}
}
}Intégrer le DAO à Play
Dans une application Play, vous injectez généralement votre UserDAO dans un contrôleur à l’aide de l’injection de dépendances. Votre contrôleur peut ainsi interagir avec la base de données.
Vous devez configurer la DI de Play (par exemple avec Guice) afin de fournir une instance de Database et de UserDAO.
import play.api.mvc._
import play.api.libs.json._
import scala.concurrent.ExecutionContext
import javax.inject._
// Assuming User and UserDAO are defined as before
@Singleton
class UserController @Inject()(cc: ControllerComponents, userDAO: UserDAO)
(implicit ec: ExecutionContext) extends AbstractController(cc) {
def listUsers = Action.async {
userDAO.findAll().map { users =>
Ok(Json.toJson(users))
}
}
def createUser = Action.async(parse.json) {
request =>
request.body.validate[User].map { user =>
userDAO.insert(user).map(u => Created(Json.toJson(u)))
}.getOrElse(Future.successful(BadRequest("Invalid User Data")))
}
}Vérification rapide : table Slick
Considérez la classe de cas Scala suivante et un mappage Slick Table partiellement défini :
case class Product(id: Option[Int], name: String, price: Double)Quelle ligne complète correctement la projection * pour la table Product, en supposant que les colonnes id, name et price sont définies ?
Récapitulatif : intégration d’une base de données
Dans cette leçon, nous avons étudié comment intégrer des bases de données à vos applications Play Framework avec Slick.
- Nous avons découvert le rôle de Slick en tant que bibliothèque de mappage relationnel fonctionnel (FRM).
- Nous avons vu comment ajouter les dépendances Slick et configurer la base de données dans
application.conf. - Vous avez appris à définir des classes de cas Scala et à les associer à des tables de base de données à l’aide de la classe
Tablede Slick. - Nous avons présenté le modèle DAO pour organiser les opérations sur la base de données, avec des exemples d’insertion et d’interrogation des données.
- Enfin, nous avons abordé l’intégration de ces opérations de DAO dans les contrôleurs Play pour créer des points d’accès d’API web.
Maîtriser l’intégration des bases de données est essentiel pour créer des applications Play robustes et pilotées par les données !
Questions Fréquemment Posées
La leçon « Intégration de bases de données avec Slick/Doobie » est-elle gratuite ?
Oui — le texte complet de « Intégration de bases de données avec Slick/Doobie » 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 3 leçons au total.
Qu'est-ce que j'apprendrai dans « Intégration de bases de données avec Slick/Doobie » ?
Apprenez à intégrer des bases de données à votre application Play à l’aide d’ORM et de bibliothèques Scala populaires tels que Slick ou Doobie. 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 3 sur 3.
Combien de temps prend la leçon « Intégration de bases de données avec Slick/Doobie » ?
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
- Principes fondamentaux de Play Framework
- Construire des API RESTful avec Play
- Intégration de bases de données avec Slick/Doobie