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.