初めてのScalaでDBアクセスをした。

2016/11/26(土)に、
株式会社セプテーニ・オリジナル様のScalaもくもく会に参加させて頂きました。
遅れ馳せながら、そのときに実施したことのメモです。

# 環境
* MacBook Pro (Retina 13-inch、Early 2015)
* OS X El Capitan 10.11.6
* Java 1.8.0_102
* IntelliJ IDEA CE 2016.3

# 実施したこと
引数で受け取った文字列を、インメモリデータベースにINSERTし、
インメモリデータベースのSELECT結果をコンソール出力する、という、
簡単なものを作成しました。

# はまったこと
* Intelli Jから実行するとき、"main method should be static"が出る
  - 「HelloWorld.scala$」ではなく、「HelloWorld.scala」を指定して実行する
    + 「HelloWorld.scala$」をラップしたのが「HelloWorld.scala」であるらしい。
* Intelli Jでsbtプロジェクトを作成した際、「New ->」に「Scala Class」が出てこない
  - ビルド中・ライブラリダウンロード中だった
  - 「src -> main -> scala」配下を選択中でないと出てこない
* そもそも、H2のインメモリDBの使い方がわからない
  - sbtによってダウンロードされたJARを起動して、H2のインメモリファイルを作成
    + 「.ivy2」ディレクトリ配下に、実体はまとめられているらしい
    + Mavenの「.m2/repository」のようなもの？
* ブラウザからH2のDBファイルに、テーブルを作成したにも関わらず、アプリケーションからはアクセスできない
  - ファイル参照方法を間違えていた…
* Scalaは++、--ができない
  - i += 1とかやる必要があるらしい
* ListにAddできない
  - ScalaのListがイミュータブルであるため
  - 再生成する必要あり
  - >> Scalaをはじめとする関数型プログラミングでは、List（コレクション）に要素を追加する必要がある場合、そのロジックがおかしいのではないかと疑ってください。
コレクションは基本的にImmutable（不変）であるべきです。
https://teratail.com/questions/7560
* テーブルへの動的なINSERT文の発行方法がわからない
  - 以下が発生
    + Error:(40, 106) could not find implicit value for parameter session: scalikejdbc.DBSession
        sql"insert into members (name, created_at) values (${userDto.name}, current_date())".update.apply()
    + Error:(40, 106) not enough arguments for method apply: (implicit session: scalikejdbc.DBSession)Int in class SQLUpdate.
Unspecified value parameter session.
        sql"insert into members (name, created_at) values (${userDto.name}, current_date())".update.apply()
  - `DB autoCommit { implicit session =>`とせず、`sql"insert into`と書き始めていた
* INSERT文発行時に`Connection pool is not yet initialized.(name:'default)`が発生する
  - 一度DBs.setupAll()やったら、CloseまでConnectしているイメージだったが、そうではないらしい
* コンストラクタに書いたメソッドが、別クラスのフィールドで`New ClassA`と書くと、実行されないらしい
  - コンストラクタの書き方が間違っていた。`def ClassA(): Unit = {}`と書いてしまうと、**ClassAというメソッド** になってしまう
* SELECT文の結果を、プレーンなテキストで出力することができず、「Some(a)」と出力されてしまう。
  - `asInstanceOf[Some[String]`でキャストして、`Some#flatten`を使用する
    + `Error:(30, 72) Cannot prove that String <:< Option[B].`が発生
  - そもそも、ScalikeJDBCを使用し、SELECT結果をANYで受け取るのが間違い、と考えられる
    + scalikejdbc.SQLSyntaxSupportクラスを継承した、取得結果を格納するDTOを作成する
* SQLが読みにくい
  - SQLInterpolation codeを使用していた。1.6にて追加された、Query DSLを使用すべき、とのこと
    + http://scalikejdbc.org/documentation/query-dsl.html
* SQLSyntaxSupportを使ったクラスで、tableNameなどをOverrideすることができない
  - `val`が必要だった
* ```
    val m = MemberDto.syntax("m")
    val members = withSQL { select.from(MemberDto as m) }.map(MemberDto(m)).list.apply()```がコンパイルエラーになる
  - `MemberDto`に`apply(SyntaxProvider)(WrappedResultSet)`と `apply(MemberDto)(WrappedResultSet)`を実装していなかった
  - sessionがなかった
*  scalikejdbc.InvalidColumnNameExceptionが発生する
  - タイポ
    + フィールド名：create_id
    + apply：created_at
    + テーブル名：created_at


# 結果
Scala＋ScalikeJDBCを使用し、
DBアクセスするコンソールアプリケーションを作成することができました。
https://github.com/naokiur/Scala-sandbox/tree/master/src/main

# 参考にさせて頂きました
http://scalikejdbc.org/documentation/query-dsl.html
https://github.com/scalikejdbc/scalikejdbc-cookbook/blob/master/ja/02_quicktour.md
https://github.com/scalikejdbc/scalikejdbc-cookbook/blob/master/ja/05_sql_template.md
https://www.jetbrains.com/help/idea/2016.3/debug-tool-window-watches.html
https://dwango.github.io/scala_text/trait.html
http://www.h2database.com/html/functions.html#current_date
http://tech.furyu.jp/blog/?p=3078
http://www.walbrix.com/spring-scala/src/examples/scala/com/walbrix/spring/ProductRequestHandler.scala