Integrazione dei database con Slick/Doobie
Impari a integrare i database nella Sua applicazione Play utilizzando ORM o librerie Scala diffuse, come Slick o Doobie.
Integrazione dei database con Slick/Doobie è una lezione Scala for Backend Engineering & Functional Programming gratuita su CoddyKit. Questa è la lezione 3 di 3. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Scala for Backend Engineering & Functional Programming, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Scala for Backend Engineering & Functional Programming include 3 lezioni in totale.
Perché integrare i database?
Le applicazioni web devono spesso archiviare e recuperare dati in modo persistente. Questi dati possono essere profili utente, informazioni sui prodotti o articoli di blog.
- Persistenza: i dati rimangono disponibili anche dopo il riavvio dell'applicazione.
- Scalabilità: consente di gestire grandi quantità di dati e molti utenti simultanei.
- Affidabilità: garantisce l'integrità e la possibilità di recuperare i dati.
L'integrazione di un database è fondamentale per qualsiasi applicazione web dinamica realizzata con Play Framework.
Slick e Doobie: strumenti DB di Scala
Scala offre librerie potenti per interagire con i database; Slick e Doobie sono due scelte diffuse.
- Slick: una libreria di Functional Relational Mapping (FRM). Consente di lavorare con i database in modo tipizzato e funzionale, astraendo SQL.
- Doobie: un livello JDBC puramente funzionale. Offre un controllo diretto sulle query SQL, integrandosi con paradigmi di programmazione funzionale come Cats Effect.
In questa lezione ci concentreremo su Slick grazie al suo livello di astrazione più elevato, che spesso semplifica l'integrazione iniziale con Play Framework.
Configurare Slick in Play
Per prima cosa, aggiunga Slick e un driver del database al file build.sbt. Utilizzeremo H2, un database in memoria, per semplificare la configurazione.
Configuri quindi la connessione al database in 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"
)Configurazione del database
Aggiunga queste righe a conf/application.conf per configurare il database H2 e il profilo Slick. slick.dbs.default.profile specifica il tipo di database.
play.db.prototype.slick definisce un modello per le connessioni al database.
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}
}Definire il modello (tabella Slick)
In Slick, le tabelle del database vengono rappresentate come classi Scala che estendono slick.jdbc.H2Profile.api.Table. Ogni colonna viene associata a un tipo Scala.
Definiamo un TableQuery per ogni tabella, che costituisce il punto di accesso per le query.
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]Codice: creazione della tabella e dello schema
Questo esempio eseguibile mostra come definire una tabella User e crearne lo schema in un database H2 in memoria. Il metodo db.run esegue le operazioni sul database in modo asincrono.
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()
}
}
}Pattern DAO per le operazioni
Il pattern Data Access Object (DAO) aiuta a incapsulare le operazioni sul database. Separa la logica di business dell'applicazione dalla logica di persistenza.
Un UserDAO conterrebbe metodi per inserire, interrogare, aggiornare ed eliminare oggetti 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)
}
}Codice: inserimento e interrogazione dei dati
Ecco come inserire un nuovo utente e poi interrogare tutti gli utenti del database utilizzando i metodi DAO appena definiti.
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()
}
}
}Integrare il DAO in Play
In un'applicazione Play, in genere si inietta UserDAO in un controller tramite la dependency injection. In questo modo le azioni del controller possono interagire con il database.
Configurerebbe la DI di Play (ad esempio Guice) per fornire un'istanza di Database e 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")))
}
}Verifica rapida: tabella Slick
Consideri la seguente case class Scala e una mappatura Slick Table definita parzialmente:
case class Product(id: Option[Int], name: String, price: Double)Quale riga completa correttamente la proiezione * per la tabella Product, supponendo che le colonne id, name e price siano definite?
Riepilogo: integrazione dei database
In questa lezione abbiamo esplorato come integrare i database nelle applicazioni Play Framework utilizzando Slick.
- Abbiamo esaminato il ruolo di Slick come libreria di Functional Relational Mapping (FRM).
- Abbiamo visto come configurare le dipendenze di Slick e il database in
application.conf. - Ha visto come definire case class Scala e associarle alle tabelle del database utilizzando la classe
Tabledi Slick. - Abbiamo introdotto il pattern DAO per organizzare le operazioni sul database e fornito esempi di inserimento e interrogazione dei dati.
- Infine, abbiamo accennato all'integrazione di queste operazioni DAO nei controller Play per gli endpoint delle API web.
Padroneggiare l'integrazione dei database è fondamentale per creare applicazioni Play robuste e basate sui dati!
Impara Scala con un tutor IA — gratis
Scrivi ed esegui vero codice nel tuo browser, ricevi aiuto istantaneo da un tutor IA disponibile 24/7, e riprendi da dove hai lasciato sul web o nell'app.
- Corsi
- 39
- Lezioni
- 143
Domande Frequenti
La lezione «Integrazione dei database con Slick/Doobie» è gratuita?
Sì — il testo completo di «Integrazione dei database con Slick/Doobie» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Scala for Backend Engineering & Functional Programming, passa a CoddyKit PRO. Il corso Scala for Backend Engineering & Functional Programming include 3 lezioni in totale.
Cosa imparerò in «Integrazione dei database con Slick/Doobie»?
Impari a integrare i database nella Sua applicazione Play utilizzando ORM o librerie Scala diffuse, come Slick o Doobie. Eserciti Scala for Backend Engineering & Functional Programming con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Scala for Backend Engineering & Functional Programming?
Non è richiesta alcuna esperienza precedente. Scala for Backend Engineering & Functional Programming su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 3.
Quanto tempo richiede la lezione «Integrazione dei database con Slick/Doobie»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Scala for Backend Engineering & Functional Programming?
Sì. Ogni lezione Scala for Backend Engineering & Functional Programming include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Fondamenti di Play Framework
- Creazione di API RESTful con Play
- Integrazione dei database con Slick/Doobie