Kotlin初心者が Exposed を使ってMySQLに日付型をINSERTするときにしばらくはまったのでメモしておきます。
はまった経緯
こんな感じのテーブルをつくりまして、
create table app_test_logs (
id integer auto_increment primary key,
log_datetime datetime not null,
ops_id int not null,
created_at datetime not null,
updated_at datetime not null
);
Ktではこんなオブジェクトを書きまして、
object AppTestLogs : Table("app_test_logs") {
val id = integer("id").autoIncrement().primaryKey()
val logDatetime = datetime("log_datetime")
val opsId = integer("ops_id")
val createdAt = datetime("created_at")
val updatedAt = datetime("updated_at")
}
実際にこんな感じで登録してみようとしたときに、
AppTestLogs.insert {
val cal = Calendar.getInstance()
cal.set(Calendar.YEAR, 2017)
cal.set(Calendar.MONTH, 8 -1)
cal.set(Calendar.DAY_OF_MONTH, 25)
cal.set(Calendar.HOUR_OF_DAY, 12)
cal.set(Calendar.MINUTE, 11)
cal.set(Calendar.SECOND, 15)
it[logDatetime] = cal.time // <- エラーになる
it[opsId] = 1
}
InteliJさんがいうには、Column / DateTime にそんなものはいらないぞ、と言われているようでした。
試行錯誤
ならば、これでどうか。
it[logDatetime] = java.util.Date(cal.timeInMillis) // <- エラー :(
じゃあこんどこそ!
it[logDatetime] = java.sql.Date(cal.timeInMillis) // <- エラー :(
あれー?
いろいろぐぐってみたのですが、はまっている人がいないようだったのでじゃあソース見てみるかと。
import org.joda.time.DateTime
あ、このひとInteliJさんもサジェストしてた。
import org.joda.time.DateTime
...
it[logDatetime] = DateTime(cal.timeInMillis) // 通った!!!
override fun notNullValueToDB(value: Any): Any {
if (value is DateTime) {
val millis = value.millis
if (time) {
return java.sql.Timestamp(millis)
}
else {
return java.sql.Date(millis)
}
}
return value
}
この辺ですかね。
こっちみると、java.sql.Date
/ java.sql.Timestamp
もごにょごにょしてるので、なんか入れてくれても良さそうなのに。
とりあえず、Exposedライブラリの日付型使うときは、 org.joda.time.DateTime
使うと良さそうというお話でした。
コードサンプル
だいたいこんな感じです。
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.joda.time.DateTime
object AppTestLogs : Table("app_test_logs") {
val id = integer("id").autoIncrement().primaryKey()
val logDatetime = datetime("log_datetime")
val opsId = integer("ops_id")
val createdAt = datetime("created_at")
val updatedAt = datetime("updated_at")
}
fun main(args: Array<String>) {
loadLogData()
}
fun loadLogData () {
Database.connect("jdbc:mysql://localhost/mydb", "com.mysql.jdbc.Driver","myuser","password")
transaction {
AppTestLogs.insert {
val cal = Calendar.getInstance()
cal.set(Calendar.YEAR, 2017)
cal.set(Calendar.MONTH, 8 -1)
cal.set(Calendar.DAY_OF_MONTH, 25)
cal.set(Calendar.HOUR_OF_DAY, 12)
cal.set(Calendar.MINUTE, 11)
cal.set(Calendar.SECOND, 15)
it[logDatetime] = DateTime(cal.timeInMillis)
it[opsId] = 1
val currentTime = DateTime(Calendar.getInstance().timeInMillis)
it[createdAt] = DateTime(currentTime)
it[updatedAt] = DateTime(currentTime)
}
}
}