どんな DB にも接続できる? dbconsole
dbconsole という新しいツールを公開しました。
これは DB 接続のための sbt console です。
https://github.com/seratch/scalikejdbc/tree/master/scalikejdbc-cli
インストールは簡単です。Windows にはまだ対応していません。 (2012/12/12 追記) id:rabitarochan が Windows 対応をしてくれました!
curl -L http://git.io/dbconsole | sh source ${HOME}/.bash_profile
Windows の場合は
http://git.io/dbconsole.bat
をダウンロードして実行してください。
ヘルプを見てみましょう。
$ dbconsole -h dbconsole is an extended sbt console to connect database easily. Usage: dbconsole [OPTION]... [PROFILE] General options: -e, --edit edit configuration, then exit -c, --clean clean sbt environment, then exit -h, --help show this help, then exit
早速 sandbox のデータベースを使って試してみます。
sandbox はインストール時に用意されたファイルベースの h2 database です。dbconsole -e で確認すると以下のような設定があらかじめされています。
sandbox.jdbc.url=jdbc:h2:file:db/sandbox sandbox.jdbc.username= sandbox.jdbc.password= #mysql.jdbc.url=jdbc:mysql://localhost:3306/dbname #postgres.jdbc.url=jdbc:postgresql://localhost:5432/dbname #oracle.jdbc.url=jdbc:oracle:thin:@localhost:1521:dbname
dbconsole は起動時に引数にプロファイル(設定の prefix)を渡します。あとは sbt が起動するのを少し待ちます。初回は依存ライブラリの解決などで少し時間がかかってしまうと思います。
$ dbconsole sandbox Starting sbt console for sandbox... [info] Set current project to default-8d98e7 (in build file:/Users/seratch/bin/scalikejdbc-cli/) [info] Starting scala interpreter... [info] import scalikejdbc._ import scalikejdbc.StringSQLRunner._ initialize: ()Unit Welcome to Scala version 2.9.2 (Java HotSpot(TM) Client VM, Java 1.6.0_29). Type in expressions to have them evaluated. Type :help for more information. scala>
どんなテーブルがあるかは tables で確認できます。
scala> tables
IRIS
あらかじめ Iris data set を入れたテーブルが用意されています。テーブルの情報を見るには describe(String) を使います。
scala> describe("iris") Table: IRIS (The Iris flower data set is a multivariate data set introduced by Sir Ronald Fisher (1936) as an example of discrimina..) +--------------+-------------+------+-----+---------+-------+-------------+ | Field | Type | Null | Key | Default | Extra | Description | +--------------+-------------+------+-----+---------+-------+-------------+ | IRIS_ID | INTEGER(10) | NO | PRI | NULL | | | | SEPAL_LENGTH | DOUBLE(17) | NO | | NULL | | | | SEPAL_WIDTH | DOUBLE(17) | NO | | NULL | | | | PETAL_LENGTH | DOUBLE(17) | NO | | NULL | | | | PETAL_WIDTH | DOUBLE(17) | NO | | NULL | | | | SPECIES | VARCHAR(16) | NO | | NULL | | | +--------------+-------------+------+-----+---------+-------+-------------+ Indexes: "PRIMARY_KEY_2" UNIQUE, (IRIS_ID)
この出力は MySQL と PostgreSQL のものを混ぜた独自のものですが、どんな DB につないでもこのフォーマットで出力されます。この例では FK がないですが FK がある場合は FK 一覧も出力されます。Oracle では Description と Index、FK 一覧が取得できません。。
それでは SQL を実行してみましょう。
文字列に #run というメソッドが追加されているのでまずはそれを使います。結果がそれぞれ Map[String, Any] に変換されて返ってきます。
scala> "select * from iris limit 3".run res4: List[Map[String,Any]] = List(Map(PETAL_LENGTH -> 1.4, SPECIES -> setosa, IRIS_ID -> 1, SEPAL_LENGTH -> 5.1, PETAL_WIDTH -> 0.2, SEPAL_WIDTH -> 3.5), Map(PETAL_LENGTH -> 1.4, SPECIES -> setosa, IRIS_ID -> 2, SEPAL_LENGTH -> 4.9, PETAL_WIDTH -> 0.2, SEPAL_WIDTH -> 3.0), Map(PETAL_LENGTH -> 1.3, SPECIES -> setosa, IRIS_ID -> 3, SEPAL_LENGTH -> 4.7, PETAL_WIDTH -> 0.2, SEPAL_WIDTH -> 3.2))
run はどんな結果でも List[Map[String,Any]] という型で結果を返します。
scala> "select count(1) from iris".run res2: List[Map[String,Any]] = List(Map(COUNT(1) -> 150))
結果が一つだけなので Long だけにしたい、という場合は #as[A] を使います。
scala> "select count(1) from iris".as[Long] res3: Long = 150
結果が返ってこないかもしれない場合は #asOption[A] で受け取ります。
scala> "select species from iris where iris_id = 1".asOption[String] res1: Option[String] = Some(setosa) scala> "select species from iris where iris_id = 777".asOption[String] res2: Option[String] = None
一つのカラムだけで結果が複数件返ってくる場合は #asList[A] が便利です。
scala> "select iris_id from iris limit 3".asList[Int] res5: List[Int] = List(1, 2, 3)
insert などの更新系や DDL の実行も同じようにできます。
scala> "insert into iris values (151, 0.1, 0.2, 0.3, 0.4, 'xxx');".as[Boolean] res6: Boolean = false scala> "create table members (id int primary key, name varchar(256), created_at timestamp)".run res6: List[Map[String,Any]] = List(Map(RESULT -> false)) scala> tables IRIS MEMBERS
トランザクションを扱いたい場合は ScalikeJDBC のDB.localTx などを使ってください。
https://github.com/seratch/scalikejdbc/wiki/GettingStartedInJapanese
scala> DB localTx { implicit session => | "insert into iris values (152, 0.1, 0.2, 0.3, 0.4, 'yyy');".run | throw new RuntimeException | } java.lang.RuntimeException at $anonfun$1.apply(<console>:16) at $anonfun$1.apply(<console>:14) at scalikejdbc.DB$$anonfun$localTx$2$$anonfun$apply$1.apply(DB.scala:606) at scala.util.control.Exception$Catch.apply(Exception.scala:88) at scalikejdbc.DB$$anonfun$localTx$2.apply(DB.scala:604) ... scala> "select * from iris where iris_id = 152".run res0: List[Map[String,Any]] = List()
現在は MySQL、PostgreSQL、Oracle、H2、HSQLDB、Derby、SQLite であれば dbconsole -e で設定を追加するだけですぐにつながるようになっています。
カスタマイズしたい場合は ${HOME}/bin/scalikejdbc-cli/build.sbt を書き換えてください。