13
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

slick3.1系 slick-codegenのカスタマイズあれこれ

Last updated at Posted at 2016-06-11

いつになってもDBモデルを手で作成するのは単調で面倒くさい作業です
特にテーブルが100も200もあるシステムなんかのローカル環境なんかはmwbで変更しまくってレビューして一気に作る場面も多いハズ...たぶん

こんな時の強い味方 slick-codegenなんですが
デフォだと微妙に使いづらい場面もチラホラ

その1
日付型がデフォでjava.sql.Timestampなのでorg.joda.time.DateTimeにしたい
-> これはtototoshiさんのslick-joda-mapperが解決してくれます

その2
mysqlにある便利な機能の一つで
更新する度に日時を更新してくれたり、作成した時に日時を自動登録してくれたりするカラムオプションがあるんですが
ジェネって作ったmodelだとこいつらにnullぶち込んじゃって機能しないので
毎回こんな感じのことをする必要があるのでなんとかしたい。もう、いるだけでダメな感じ

こんなテーブルの場合

CREATE TABLE people (
id bigint(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age  INT NOT NULL,
addressId   INT NOT NULL,
create_at datetime DEFAULT CURRENT_TIMESTAMP, /*←これとか*/
update_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, /*←これとか*/
PRIMARY KEY (id)
)

毎回mapで項目を絞る必要が....

people.map(p => (p.name, p.age, p.addressId)) += ("M Odersky",12345,1)

その2に対してmodelからそもそもそのカラムを消しちゃう感じで対応してみました

import slick.driver.JdbcProfile
import scala.concurrent.ExecutionContext.Implicits.global
import slick.driver.MySQLDriver.api._
import slick.driver.MySQLDriver
import slick.driver.JdbcProfile
import slick.{model => m}
import slick.codegen.SourceCodeGenerator
import slick.model.Model
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}

class CustomGenerator(model: m.Model) extends SourceCodeGenerator(model) {

  // add some custom imports
  override def code = "import com.github.tototoshi.slick.MySQLJodaSupport._\n" + "import org.joda.time.DateTime\n" + super.code
  override def Table = new Table(_) {
    override def autoIncLastAsOption = true
    override def Column = new Column(_) {
      override def rawType = model.tpe match {
        case "java.sql.Timestamp" => "DateTime" // kill j.s.Timestamp
        case "java.sql.Date" => "DateTime" // kill j.s.Timestamp
        case _ => {
          super.rawType
        }
      }
    }
  }
}

object CodeGenWithJodaTime extends App {
  val slickDriver = "slick.driver.MySQLDriver"
  val jdbcDriver = "com.mysql.jdbc.Driver"
  val url = "jdbc:mysql://localhost/myschema"
  val outputFolder = "src/main/scala"
  val schemas = "myschema"
  val pkg = "mypkg"
  val user = "username"
  val password = "userpassword"
  val driver: JdbcProfile = slick.driver.MySQLDriver // TODO: replace this with your Slick driver
  val db = { Database.forURL(url, driver = jdbcDriver, user = user, password = password) }

  // 非同期をぶった斬って処理する
  val model = Await.result(db.run(driver.createModel(None, false)(ExecutionContext.global).withPinnedSession), Duration.Inf)

  // 登録日(create_at)と更新日(update_at)はMySql側の設定で対応するのでTablesからは除外する
  val ts = (for {
    t <- model.tables
    c = t.columns.filter(_.name != "create_at").filter(_.name != "update_at")
  } yield(slick.model.Table(t.name, c, t.primaryKey, t.foreignKeys, t.indices, t.options)))
  val fModel = Model(tables = ts)

  val codeGenFuture = new CustomGenerator(fModel).writeToFile(slickDriver, outputFolder , pkg, "Tables", "Tables.scala")
}

以上です、もっと良いやり方あれば教えていただけると嬉しいです。

13
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?