SlideShare una empresa de Scribd logo
1 de 14
Descargar para leer sin conexión
Eishay Smith (CTO & Founder)
@eishay of @42eng
on @
42go.com
Agenda
• Intro to Slick
• How we use it at FortyTwo
• Wrapping Sessions
• Generic Access Layer
About Slick
Database query library for Scala
"select * from users where id=?"
or
def get(id: Long): User =
(for(u <- UserTable if u.id is id) yield u).first
or
def get(id: Id[M]): M =
(for(f <- table if f.id is id) yield f).first
Can do: insert, update, delete, DDL and more
More About Slick
• Using Options to represent NULLs
• Creates DDLs (tests without Play)
• Type safe in and out
• Syntax safe
• Custom types
• Can use regular sql
• With type safe wrapping
Type Safe Concurrency
abstract class RSession(roSession: => Session) extends SessionWrapper(roSession)
class ROSession(roSession: => Session) extends RSession(roSession)
class RWSession(rwSession: Session) extends RSession(rwSession)
class Database @Inject() (val db: DataBaseComponent) {
  import DBSession._
 
private def rawSession = db.handle.createSession()
 
def readOnly[T](f: ROSession => T): T = {
val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.ReadOnly)
try f(new ROSession(s)) finally s.close()
}
 
def readWrite[T](f: RWSession => T): T = {
val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.Updatable))
try {
rw.withTransaction { f(new RWSession(s)) }
} finally s.close()
}
}
Using Sessions
db.readOnly { implicit s =>
// only reading from db - not in a transaction
val users = userRepo.getUsersByLastName(“Smith”)
accountRepo.getAccounts(users)
}
db.readWrite { implicit s =>
// reading and writing to db in a transaction
val users = userRepo.getUsersByLastName(“Smith”)
accountRepo.deleteAccounts(users)
userRepo.markUsersAsInactive(users)
}
db.readOnly { implicit s =>
val user = userRepo.get(userId)
emailRepo.updateEmail(user, newMail) <-- FAIL
}
DB Repo
trait Repo[M <: Model[M]] {
def get(id: Id[M])(implicit session: RSession): M
def all()(implicit session: RSession): Seq[M]
def save(model: M)(implicit session: RWSession): M
def count(implicit session: RSession): Int.
def page(page: Int = 0, size: Int = 20)
(implicit session: RSession): Seq[M]
}
DB Repo Impl
trait DbRepo[M <: Model[M]] extends Repo[M] {
protected def table: RepoTable[M]
 
//you don’t have to run the whole Play Application to get the db setup!
def descTable(): String = db.handle.withSession {
table.ddl.createStatements mkString "n"
}
 
def count(implicit session: RSession): Int = Query(table.length).first
 
def get(id: Id[M])(implicit session: RSession): M =
(for(f <- table if f.id is id) yield f).first
 
def all()(implicit session: RSession): Seq[M] = table.map(t => t).list
def page(page: Int = 0, size: Int = 20)(implicit session: RSession): Seq[M] = {
val q = for {
t <- table
} yield t
q.sortBy(_.id desc).drop(page * size).take(size).list
}
}
DB Repo Impl - Persisting
def save(model: M)(implicit session: RWSession): M = try {
val toUpdate = model.withUpdateTime(clock.now)
val result = model.id match {
case Some(id) => update(toUpdate)
case None => toUpdate.withId(insert(toUpdate))
}
} catch {
case t: SQLException => throw new SQLException(s"error persisting $model", t)
}
private def insert(model: M)(implicit session: RWSession) =
table.autoInc.insert(model)
 
private def update(model: M)(implicit session: RWSession) = {
val target = for(t <- table if t.id === model.id.get) yield t
val count = target.update(model)
assert(1 == count)
model
}
RepoTable
abstract class RepoTable[M <: Model[M]]
(db: DataBaseComponent, name: String) extends Table[M]
(db.entityName(name)) with TableWithDDL {
//standardizing the following columns for all entities
def id = column[Id[M]]("ID", O.PrimaryKey, O.Nullable, O.AutoInc)
def createdAt = column[DateTime]("created_at", O.NotNull)
def updatedAt = column[DateTime]("updated_at", O.NotNull)
def autoInc = * returning id
 
//H2 likes its column names in upper case where mysql does not mind.
//the db component should figure it out
override def column[C : TypeMapper](name: String, options: ColumnOption[C]*) =
super.column(db.entityName(name), options:_*)
}
}
Example - User
case class User(
id: Option[Id[User]] = None,
createdAt: DateTime,
updatedAt: DateTime,
firstName: String,
lastName: String
) extends Model[User] {
def withName(firstName: String, lastName: String) =
copy(firstName = firstName, lastName = lastName)
}
Example - UserRepo
@ImplementedBy(classOf[UserRepoImpl])
trait UserRepo extends Repo[User] {
def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User]
}
@Singleton
class UserRepoImpl @Inject() (val db: DataBaseComponent, val clock: Clock)
extends DbRepo[User] with UserRepo {
 
override val table = new RepoTable[User](db, "user") {
def firstName = column[String]("first_name", O.NotNull)
def lastName = column[String]("last_name", O.NotNull)
def * = id.? ~ createdAt ~ updatedAt ~ firstName ~ lastName <>
(User.apply _, User.unapply _)
}
 
def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User] =
(for (u <- table if u.lastName = lastName yield u).list
}
Q & A
Binding (with Guice)
trait DbInfo {
def database: SlickDatabase
def driverName: String
}
 
class SlickModule(dbInfo: DbInfo) extends ScalaModule {
def configure(): Unit = {
lazy val db = dbInfo.driverName match {
case MySQL.driverName => new MySQL(dbInfo.database)
case H2.driverName => new H2(dbInfo.database)
}
bind[DataBaseComponent].toInstance(db)
bind[Database].in(classOf[Singleton])
}
}

Más contenido relacionado

La actualidad más candente

Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)croquiscom
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional ProgrammingDmitry Buzdin
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Datagreenwop
 
Cycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveCycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveEugene Zharkov
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friendkikoalonsob
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum Ukraine
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to PythonUC San Diego
 
A Tour to MySQL Commands
A Tour to MySQL CommandsA Tour to MySQL Commands
A Tour to MySQL CommandsHikmat Dhamee
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad Fabernovel
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFabio Collini
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수용 최
 
GreenDao Introduction
GreenDao IntroductionGreenDao Introduction
GreenDao IntroductionBooch Lin
 
Swift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationSwift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationJacopo Mangiavacchi
 

La actualidad más candente (19)

JDBC
JDBCJDBC
JDBC
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Sparklyr
SparklyrSparklyr
Sparklyr
 
[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)[2019-07] GraphQL in depth (serverside)
[2019-07] GraphQL in depth (serverside)
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
 
Enter The Matrix
Enter The MatrixEnter The Matrix
Enter The Matrix
 
Category theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) DataCategory theory, Monads, and Duality in the world of (BIG) Data
Category theory, Monads, and Duality in the world of (BIG) Data
 
Cycle.js: Functional and Reactive
Cycle.js: Functional and ReactiveCycle.js: Functional and Reactive
Cycle.js: Functional and Reactive
 
Database API, your new friend
Database API, your new friendDatabase API, your new friend
Database API, your new friend
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
 
Introduction to Python
Introduction to PythonIntroduction to Python
Introduction to Python
 
JDBC Core Concept
JDBC Core ConceptJDBC Core Concept
JDBC Core Concept
 
A Tour to MySQL Commands
A Tour to MySQL CommandsA Tour to MySQL Commands
A Tour to MySQL Commands
 
Talk - Query monad
Talk - Query monad Talk - Query monad
Talk - Query monad
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
Python 내장 함수
Python 내장 함수Python 내장 함수
Python 내장 함수
 
GreenDao Introduction
GreenDao IntroductionGreenDao Introduction
GreenDao Introduction
 
Swift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML PersonalizationSwift for TensorFlow - CoreML Personalization
Swift for TensorFlow - CoreML Personalization
 

Similar a Using Scala Slick at FortyTwo

Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsEleanor McHugh
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialjbellis
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersKazuhiro Sera
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRick Copeland
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemyInada Naoki
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonSiddhi
 
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...Michael Rys
 
Database queries
Database queriesDatabase queries
Database querieslaiba29012
 
Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013Samir Bessalah
 
Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02Lalit009kumar
 
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...MongoDB
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveJeff Smith
 
Deep learning study 3
Deep learning study 3Deep learning study 3
Deep learning study 3San Kim
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your CodeDrupalDay
 

Similar a Using Scala Slick at FortyTwo (20)

Slickdemo
SlickdemoSlickdemo
Slickdemo
 
Where's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord MigrationsWhere's My SQL? Designing Databases with ActiveRecord Migrations
Where's My SQL? Designing Databases with ActiveRecord Migrations
 
PyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorialPyCon 2010 SQLAlchemy tutorial
PyCon 2010 SQLAlchemy tutorial
 
ScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for BeginnersScalikeJDBC Tutorial for Beginners
ScalikeJDBC Tutorial for Beginners
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and MingRapid and Scalable Development with MongoDB, PyMongo, and Ming
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
 
PofEAA and SQLAlchemy
PofEAA and SQLAlchemyPofEAA and SQLAlchemy
PofEAA and SQLAlchemy
 
Introduction to Quill
Introduction to QuillIntroduction to Quill
Introduction to Quill
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in Python
 
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
U-SQL Killer Scenarios: Custom Processing, Big Cognition, Image and JSON Proc...
 
Database queries
Database queriesDatabase queries
Database queries
 
Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013Big Data Analytics with Scala at SCALA.IO 2013
Big Data Analytics with Scala at SCALA.IO 2013
 
Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02Lecture05sql 110406195130-phpapp02
Lecture05sql 110406195130-phpapp02
 
DataMapper
DataMapperDataMapper
DataMapper
 
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
MongoDB London 2013: Basic Replication in MongoDB presented by Marc Schwering...
 
Lobos Introduction
Lobos IntroductionLobos Introduction
Lobos Introduction
 
Tools for Making Machine Learning more Reactive
Tools for Making Machine Learning more ReactiveTools for Making Machine Learning more Reactive
Tools for Making Machine Learning more Reactive
 
Code Generation
Code GenerationCode Generation
Code Generation
 
Deep learning study 3
Deep learning study 3Deep learning study 3
Deep learning study 3
 
Sequel
SequelSequel
Sequel
 
Your Entity, Your Code
Your Entity, Your CodeYour Entity, Your Code
Your Entity, Your Code
 

Último

Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Bhuvaneswari Subramani
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 

Último (20)

Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 

Using Scala Slick at FortyTwo

  • 1. Eishay Smith (CTO & Founder) @eishay of @42eng on @ 42go.com
  • 2. Agenda • Intro to Slick • How we use it at FortyTwo • Wrapping Sessions • Generic Access Layer
  • 3. About Slick Database query library for Scala "select * from users where id=?" or def get(id: Long): User = (for(u <- UserTable if u.id is id) yield u).first or def get(id: Id[M]): M = (for(f <- table if f.id is id) yield f).first Can do: insert, update, delete, DDL and more
  • 4. More About Slick • Using Options to represent NULLs • Creates DDLs (tests without Play) • Type safe in and out • Syntax safe • Custom types • Can use regular sql • With type safe wrapping
  • 5. Type Safe Concurrency abstract class RSession(roSession: => Session) extends SessionWrapper(roSession) class ROSession(roSession: => Session) extends RSession(roSession) class RWSession(rwSession: Session) extends RSession(rwSession) class Database @Inject() (val db: DataBaseComponent) {   import DBSession._   private def rawSession = db.handle.createSession()   def readOnly[T](f: ROSession => T): T = { val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.ReadOnly) try f(new ROSession(s)) finally s.close() }   def readWrite[T](f: RWSession => T): T = { val s = rawSession.forParams(rsConcurrency = ResultSetConcurrency.Updatable)) try { rw.withTransaction { f(new RWSession(s)) } } finally s.close() } }
  • 6. Using Sessions db.readOnly { implicit s => // only reading from db - not in a transaction val users = userRepo.getUsersByLastName(“Smith”) accountRepo.getAccounts(users) } db.readWrite { implicit s => // reading and writing to db in a transaction val users = userRepo.getUsersByLastName(“Smith”) accountRepo.deleteAccounts(users) userRepo.markUsersAsInactive(users) } db.readOnly { implicit s => val user = userRepo.get(userId) emailRepo.updateEmail(user, newMail) <-- FAIL }
  • 7. DB Repo trait Repo[M <: Model[M]] { def get(id: Id[M])(implicit session: RSession): M def all()(implicit session: RSession): Seq[M] def save(model: M)(implicit session: RWSession): M def count(implicit session: RSession): Int. def page(page: Int = 0, size: Int = 20) (implicit session: RSession): Seq[M] }
  • 8. DB Repo Impl trait DbRepo[M <: Model[M]] extends Repo[M] { protected def table: RepoTable[M]   //you don’t have to run the whole Play Application to get the db setup! def descTable(): String = db.handle.withSession { table.ddl.createStatements mkString "n" }   def count(implicit session: RSession): Int = Query(table.length).first   def get(id: Id[M])(implicit session: RSession): M = (for(f <- table if f.id is id) yield f).first   def all()(implicit session: RSession): Seq[M] = table.map(t => t).list def page(page: Int = 0, size: Int = 20)(implicit session: RSession): Seq[M] = { val q = for { t <- table } yield t q.sortBy(_.id desc).drop(page * size).take(size).list } }
  • 9. DB Repo Impl - Persisting def save(model: M)(implicit session: RWSession): M = try { val toUpdate = model.withUpdateTime(clock.now) val result = model.id match { case Some(id) => update(toUpdate) case None => toUpdate.withId(insert(toUpdate)) } } catch { case t: SQLException => throw new SQLException(s"error persisting $model", t) } private def insert(model: M)(implicit session: RWSession) = table.autoInc.insert(model)   private def update(model: M)(implicit session: RWSession) = { val target = for(t <- table if t.id === model.id.get) yield t val count = target.update(model) assert(1 == count) model }
  • 10. RepoTable abstract class RepoTable[M <: Model[M]] (db: DataBaseComponent, name: String) extends Table[M] (db.entityName(name)) with TableWithDDL { //standardizing the following columns for all entities def id = column[Id[M]]("ID", O.PrimaryKey, O.Nullable, O.AutoInc) def createdAt = column[DateTime]("created_at", O.NotNull) def updatedAt = column[DateTime]("updated_at", O.NotNull) def autoInc = * returning id   //H2 likes its column names in upper case where mysql does not mind. //the db component should figure it out override def column[C : TypeMapper](name: String, options: ColumnOption[C]*) = super.column(db.entityName(name), options:_*) } }
  • 11. Example - User case class User( id: Option[Id[User]] = None, createdAt: DateTime, updatedAt: DateTime, firstName: String, lastName: String ) extends Model[User] { def withName(firstName: String, lastName: String) = copy(firstName = firstName, lastName = lastName) }
  • 12. Example - UserRepo @ImplementedBy(classOf[UserRepoImpl]) trait UserRepo extends Repo[User] { def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User] } @Singleton class UserRepoImpl @Inject() (val db: DataBaseComponent, val clock: Clock) extends DbRepo[User] with UserRepo {   override val table = new RepoTable[User](db, "user") { def firstName = column[String]("first_name", O.NotNull) def lastName = column[String]("last_name", O.NotNull) def * = id.? ~ createdAt ~ updatedAt ~ firstName ~ lastName <> (User.apply _, User.unapply _) }   def usersWithLastName(lastName: String)(implicit session: RSession): Seq[User] = (for (u <- table if u.lastName = lastName yield u).list }
  • 13. Q & A
  • 14. Binding (with Guice) trait DbInfo { def database: SlickDatabase def driverName: String }   class SlickModule(dbInfo: DbInfo) extends ScalaModule { def configure(): Unit = { lazy val db = dbInfo.driverName match { case MySQL.driverName => new MySQL(dbInfo.database) case H2.driverName => new H2(dbInfo.database) } bind[DataBaseComponent].toInstance(db) bind[Database].in(classOf[Singleton]) } }