Cookbook
This section of the manual is for solutions to common questions.
Mapping more than 22 fields
Problem
You have a table with more than 22 fields, and the Scala 2 compiler has told you:
too many elements for tuple: 23, allowed: 22
Solution
Switch from using a tuple in your default projection to using an HList.
First, add the HList imports:
sourceimport slick.collection.heterogeneous._
import slick.collection.heterogeneous.syntax._
Your case class and table definition are as unchanged, but your default projection ( the *
method) changes:
sourcecase class Row(id: Int, name: String /* ... as many as you like */)
class MyTable(tag: Tag) extends Table[Row](tag, "ROW") {
def id = column[Int]("ID", O.PrimaryKey)
def name = column[String]("NAME")
/* ... as many as you like */
def * = (id :: name /* as many as you like... */ :: HNil).mapTo[Row]
}
Track the Number of Query Compilations
Problem
Query compilation can be expensive. We can use the Compiled
construct to avoid re-compiling queries. However, it can also be easy to accidentally forget to use this construct or revert its usage. When this happens in a high-traffic deployment, query times and CPU usage can increase drastically.
To identify this type of regression, we’d like to track the number of query compilations. We might then expose this count as an application metric and setup an alert which triggers when an abnormally high number of query compilations occur.
Solution
To track the number of query compilations, we can override the computeQueryCompiler
method in our profile. The new QueryCompiler
will have an additional phase, which simply increments a counter.
sourceimport slick.jdbc.JdbcProfile
import slick.compiler._
import java.util.concurrent.atomic.AtomicLong
trait MyProfile extends JdbcProfile {
// This counter can be accessed from an instance of `MyProfile`
// and exposed as an application metric.
final val queryCompilationCounter: AtomicLong = new AtomicLong(0)
// This method gets called to setup the QueryCompiler.
// We'll attach a CompilerPhase that just increments the compilation counter
// and leave the compiler otherwise unchanged.
override def computeQueryCompiler: QueryCompiler = {
val phase = new Phase {
override type State = this.type
override val name: String = "IncrementQueryCompilationCounter"
override def apply(state: CompilerState): CompilerState = {
// When this Phase gets applied, it just increments the counter and
// passes the CompilerState through unchanged.
queryCompilationCounter.incrementAndGet()
state
}
}
super.computeQueryCompiler + phase
}
}