Skip to content

Getting Started

JeremyChase edited this page Nov 18, 2011 · 21 revisions

Adding ScalaQuery to Your Project

The current release is ScalaQuery 0.9.0 for Scala 2.8.0. It is available from the Scala-Tools repository. If you are using sbt, add a dependency to ScalaQuery to your project like this:

libraryDependencies += "org.scalaquery" %% "scalaquery" % "0.9.0"

You can also use Maven or download the JAR directly. Except for the Scala 2.8.0 library, ScalaQuery has no other dependencies. See here for building ScalaQuery yourself.

Database Connections

ScalaQuery is built on top of JDBC and requires a JDBC driver to access a database system. All database calls are are made through a Session (a wrapper for a JDBC Connection) which is obtained from a Database by using either withSession or withTransaction. Both will close the session automatically at the end of the block.

Once the session is obtained, there are two ways of using it. The safest (regarding compile-time checks and typesafety) is to pass the session to the database calls explicitly:

import org.scalaquery.session._

val myQuery = ...
val db = Database.forURL("jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
db withSession { session => // passes the session
  myQuery.list()(session)   // to .list() explicitly
}

The other (more convenient but less typesafe) way is to import an implicit which tries to provide the session itself:

import org.scalaquery.session._
import org.scalaquery.session.Database.threadLocalSession // the implicit in question

val myQuery = ...
val db = Database.forURL("jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
db withSession {
  myQuery.list() // session is passed implicitly
}

This is the most convenient, but less safe way of using a session as the implicit turns a compile-time check into a runtime check: Once the implicit is imported, the compiler has no way of guaranteeing that your database calls have a valid session available. You have been warned.

Tables

In order to build queries you need to declare a table object for each table, e.g.:

import org.scalaquery.ql.basic.{BasicTable => Table}
import org.scalaquery.ql.TypeMapper._
import org.scalaquery.ql._
...

  object Users extends Table[(Int, String, Option[String])]("users") {
    def id = column[Int]("id", O NotNull)
    def first = column[String]("first", O Default "NFN", O DBType "varchar(64)")
    def last = column[Option[String]]("last")
    def * = id ~ first ~ last
  }

  object Orders extends Table[(Int, Int, String, Boolean, Option[Boolean])]("orders") {
    def userID = column[Int]("userID", O NotNull)
    def orderID = column[Int]("orderID", O NotNull)
    def product = column[String]("product")
    def shipped = column[Boolean]("shipped", O Default false, O NotNull)
    def rebate = column[Option[Boolean]]("rebate", O Default Some(false))
    def * = userID ~ orderID ~ product ~ shipped ~ rebate
  }

The following types for columns are supported out of the box: Boolean, java.sql.Blob, Byte, java.sql.Clob, java.sql.Date, Double, Float, Int, Long, String, java.sql.Time, java.sql.Timestamp. Every table object must be parameterized with a tuple of the types of all columns and it must define a “*” projection of the same type (using the projection operator “~”).

If the columns do not already exist in the database, ScalaQuery can create them (requires a Session):

import  org.scalaquery.ql.basic.BasicDriver.Implicit._


...

      (Users.ddl ++ Orders.ddl) create

Column options like O NotNull or O Default which are specified in the table object are used for creating the tables through ScalaQuery. If you create the tables in some other way, you can omit these options. There is currently no way to define indexes in ScalaQuery, so you should do that manually (or with a setup script which also creates the tables) for production systems.

The BasicDriver import provides database engine-specific functionality. It is also needed for constructing and performing queries. There are special drivers with extended functionality for Oracle (OracleDriver), MySQL (MySQLDriver), Postgres (PostgresDriver), SQLite (SQLiteDriver), H2 (H2Driver), Apache Derby (DerbyDriver) and HyperSQL (HsqldbDriver) which can be used instead of BasicDriver on these database systems.

Clone this wiki locally