In the comparisons presented on this page the following data model will be assumed:
case class Coffee ( name : String, supplier : Supplier, price : Double, sales : Int, total : Int )
case class Supplier ( name : String, street : String, city : String, state : String, zip : String )
Framework initialization
-
SORM
import sorm._ object Db extends Instance ( entities = Set( Entity[Coffee](), Entity[Supplier]() ), url = "jdbc:h2:mem:test" ) -
Slick
import scala.slick.driver.H2Driver.simple._ import Database.threadLocalSession object Suppliers extends Table[(Int, String, String, String, String, String)]("SUPPLIERS") { def id = column[Int]("SUP_ID", O.PrimaryKey) def name = column[String]("SUP_NAME") def street = column[String]("STREET") def city = column[String]("CITY") def state = column[String]("STATE") def zip = column[String]("ZIP") def * = id ~ name ~ street ~ city ~ state ~ zip } object Coffees extends Table[(String, Int, Double, Int, Int)]("COFFEES") { def name = column[String]("COF_NAME", O.PrimaryKey) def supID = column[Int]("SUP_ID") def price = column[Double]("PRICE") def sales = column[Int]("SALES") def total = column[Int]("TOTAL") def * = name ~ supID ~ price ~ sales ~ total def supplier = foreignKey("SUP_FK", supID, Suppliers)(_.id) } val db = Database.forURL("jdbc:h2:mem:test", driver = "org.h2.Driver")
Connections management and pooling
-
SORM
Automatic. Integrated connection pooler.
-
Slick
- Uses a single connection. With help of 3rd-party connection poolers multiple connections can be achieved.
- All db-requests must be wrapped with a
db.withSession { ... }block.
Database schema generation
-
SORM
Automatic
-
Slick
db.withSession { (Suppliers.ddl ++ Coffees.ddl).create }
Inserting
Persist the following three objects:
val supplier1 = Supplier("Acme, Inc.", "99 Market Street", "Groundsville", "CA", "95199")
val supplier2 = Supplier("Superior Coffee", "1 Party Place", "Mendocino", "CA", "95460")
val supplier3 = Supplier("The High Ground", "100 Coffee Lane", "Meadows", "CA", "93966")
-
SORM
Db.save(supplier1) Db.save(supplier2) Db.save(supplier3) -
Slick
db.withSession { Suppliers.insert(101, supplier1.name, supplier1.street, supplier1.city, supplier1.state, supplier1.zip) Suppliers.insert(49, supplier2.name, supplier2.street, supplier2.city, supplier2.state, supplier2.zip) Suppliers.insert(150, supplier3.name, supplier3.street, supplier3.city, supplier3.state, supplier3.zip) }
Querying
Collect Coffee instances having a supplier named “Superior Coffee”
-
SORM
Db.query[Coffee] .whereEqual("supplier.name", "Superior Coffee") .fetch() -
Slick
db.withSession { for { s <- Suppliers if s.name === "Superior Coffee" c <- Coffees if s.id === c.supID } yield Coffee(c.name, Supplier(s.name, s.street, s.city, s.state, s.zip), c.price, c.sales, c.total) }
Collect just the names of coffee and supplier
-
SORM
Db.query[Coffee].whereSmaller("price", 9.0).fetch() .map(c => (c.name, c.supplier.name)) -
Slick
db.withSession { for { c <- Coffees if c.price < 9.0 s <- Suppliers if s.id === c.supID } yield (c.name, s.name) }
Updating
Update sales and total of an already fetched Coffee
-
SORM*
Db.save(coffee.copy(sales = coffee.sales + 1, total = coffee.total + 23.4)) -
Slick**
db.withSession { val q = for(c <- Coffees if c.id === id) yield (c.sales, c.total) q.foreach { case (sales, total) => (Coffees.sales ~ Coffees.total) .update (sales + 1, total + 23.4) } }
* SORM automatically identifies the fetched values with help of Persisted trait. To learn more about how it works please visit this page.
** In Slick the identifier of the row has to be manually managed, by either extending the model case class to include it, or storing it separately.
Supported databases
-
SORM
- MySQL
- PostgreSQL
- H2
- HSQLDB
-
Slick
- Derby
- H2
- HSQLDB
- Microsoft Access
- Microsoft SQL Server
- MySQL
- PostgreSQL
- SQLite
Type-safety
-
SORM
Not complete. In queries and in instance declaration fields are referred with strings.
-
Slick
Queries performed with Slick are type safe.
Support for schema mapping customization
-
SORM
SORM completely hides the details of database generation from user, as such it makes it impossible to make any customizable mappings.
-
Slick
With Slick you get a fine-grain control over how the database tables get mapped.