ScalikeJDBC 3.0 コードリーディング（コネクション関係）

#1. はじめに
　これは、私がScalaを勉強している過程で、オープンソースのコードを読んでみようと思い、色々調べた事を記載しています。私は、これまでまともにオープソースのコードを読んでおらず、業務でもプログラミンをほぼ書かなくなっている者です。が、なるべく初心者でもソースコードを読むきっかけになればと思い書きました。[ScalikeJDBC](https://github.com/scalikejdbc/scalikejdbc)を選択したのは、元々ドキュメントが充実しており、簡単なサンプルアプリなら作ることが出来たので、中身に興味を持てたためです。興味は持てたのですが、なかなか理解出来ない書き方等があり、苦労もありましたが、読む事がScalaの理解にも繋がりました。まずは、主要なクラスの紹介から入って、細かいところで気付いた箇所を説明したいと思います。

以下からコードを幾つか参照させていただいています。
https://github.com/scalikejdbc/scalikejdbc

#2. コネクション
　object のDB が主要クラスとなります。DBは、trait である DBConnectionを継承しています。DBConnection は、LogSupport、LoanPattern、AutoCloseableを継承しており、java.sql.Connectionの管理を担当しています。が、DBを通じて、DBConnectionの関数を呼び出しています。
![connection_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/103773/d7a44dd0-54ec-4e63-796e-cfc24f5879dc.jpeg)

DBのメソッドを簡単に紹介します。

|メソッド|概略|
|:-----------------|:------------------|
| readOnly | 『DBSessionを受け取りAを返す関数』を引数に取る。読み取り専用の処理。|
| autoCommit| 同上で、コミット（ロールバック）を自動的に実施。|
| localTx|同一ブロックのSQLを同一トランザクション管理できます。失敗すれば全てロールバック。 |
| futureLocalTx|Futureでラップした結果を受け取り、それぞれの処理をひとつのトランザクションとして管理します。|
| withinTx|呼び出す側にてトランザクション管理（begin,commit/rollback）が必要です。|

他にも、getAllColumnsやgetColumnNames、getTableと言ったメソッドも持っている。

親のtrait である DBConnection がjava.sql.Connectionを保持していますが、その取得は点線で下にひも付けている、ConnectionPoolContextを利用しています（ScalikeJDBCのコネクションプールは後述）。
このDBConnectionもreadOnly、autoCommit等々と同名のメソッドを持っています。大きな違いは、implicit パラメータが無いところです。また、readOnlyの中では『DBSessionを引数に持ち、A を返す』関数が実行されます。

```scala:DB.scala(object)


  /**
   * Begins a read-only block easily with ConnectionPool.
   *
   * @param execution execution
   * @param context connection pool context
   * @tparam A return type
   * @return result value
   */
  def readOnly[A](execution: DBSession => A)(implicit context: CPContext = NoCPContext, settings: SettingsProvider = SettingsProvider.default): A = {
    val cp = connectionPool(context)
    using(cp.borrow()) { conn =>
      DB(conn, cp.connectionAttributes, settings).autoClose(false).readOnly(execution)
    }
  }
```


```scala:DBConnection.scala

  /**
   * Provides read-only session block.
   * @param execution block
   * @tparam A  return type
   * @return result value
   */
  def readOnly[A](execution: DBSession => A): A = {
    if (autoCloseEnabled) using(conn)(_ => execution(readOnlySession()))
    else execution(readOnlySession())
  }
```

この『DBSessionを受け取る関数』を引き渡しているところは、他のメソッドでも見られる特徴です。このおかげで、以下に記載があるように、お決まりの長い記述をコーディングしなくても済んでいます。
http://scalikejdbc.org/documentation/connection-pool.html

#3. コネクションプール
コネクションプールに関しては、サンプルにあるようにConnectionPoolのsingletonで初期化が走ります。実際には内部でaddが呼ばれて初期化が色々走っています。
当初は、ＸＸＸＸPoolクラスが沢山あって、ポイントが理解できなかったのですが、『ConnectionPoolのフレームワーク』が色々存在して、それを隠蔽する形で利用できるようにしてある事が理解できれば、すんなりわかった気がします。

![connectionpool_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/103773/67264764-5bfa-33e5-365b-8bc3edc1ccf4.jpeg)

デフォルトは、commons-dbcp2ですが、他のサイトで確認していると、HikariCPが圧倒的に処理量が多いとの記載がありました（が実際に確認はできていませんのでご注意下さい）。

#4. 気付いたところ
読んでいて気づきがあったところを書いてみたいと思います。

##メソッドの最後のthis
最初読み始めた時は、setterっぽいメソッドでどうして最後にthisを返すのか、意味がわかっていませんでした。

```scala:DBConnection.scala
  /**
   * Switches auto close mode.
   * @param autoClose auto close enabled if true
   */
  def autoClose(autoClose: Boolean): DBConnection = {
    this.autoCloseEnabled = autoClose
    this
  }
```

これは、以下の様に文章の様にコーディングするためだとようやく気づく事ができました。

```scala

DB(conn, cp.connectionAttributes, settings).autoClose(false).readOnly(execution)
```

Scala 本体のコードでも見ることができる書き方です。

```scala:Vector.scala
  override def takeRight(n: Int): Vector[A] = {
    if (n <= 0)
      Vector.empty
    else if (endIndex - n > startIndex)
      dropFront0(endIndex - n)
    else
      this
  }
```

##=> ロケットシンボル
match case だとか、関数リテラルだとかは理解出来ているつもりだったのですが、以下の構文はすぐにはピンと来ませんでした。

```scala:DBConnection.scala
  /**
   * Provides read-only session block.
   * @param execution block
   * @tparam A  return type
   * @return result value
   */
  def readOnlyWithConnection[A](execution: Connection => A): A = {
    readOnly(s => execution(s.conn))
  }
```
ずっと s を探していました。。。どこで渡されるんだろうって。
これも関数リテラルで、『DBSessionを受け取る関数』をパラメータにして、readOnlyを呼んでいる事が理解できて、ようやく読めた気がしました。
以下みたいに、型と（）を記述して、少し納得できました。

```scala
readOnly((s: DBSession) => execution(s.conn))
```

##クラス図は意外に大事
今まであまりソースコードをしっかり読んで来なかったので、ファイルがずらっと並んでいてもずっとモヤモヤしてました。処理を追っていって頭では理解できたつもりでも、もう一度見直すとモヤモヤ感からやり直しの日々でした。
それから抜け出すために、図に書きだして見ると、まずはその図が頭に浮かぶようになりました。自分はやはり図からコードをイメージするタイプなようです。
今回、書いた図（とこの文章）が初めてScalikeJDBCのソースコードを読む人の少しでも手助けになればと思います。
あと、次は"SQL"まわりの理解にチャレンジします。