2017-11-19 15 views
1

slick 3.2.1でPlay Framework 2.6を使用してWebアプリケーションを作成しています。 "NOT NULL DEFAULT CURRENT_TIMESTAMP"(私はMySQLを使用しています)のcreated_atカラムを持つテーブル "USER"にレコードを挿入しようとすると、データベースは "カラム 'created_at'をnullにすることはできません。Play「スカラー」と「Slick3」が「NOT NULL DEFAULT CURRENT_TIMESTAMP」の列に「Column xxはnullではありません」というエラーが表示されます

私はslickによって生成されたSQLが間違っていることを知っています。ステートメントは、created_at列にnullを挿入しようとしています。 created_atカラムを含まないSQLを滑らかに生成する適切な方法は何ですか?

スケーラコードの抜粋。

import org.joda.time.DateTime 

case class User(
    id: Option[Long], 
    accountId: Long, 
    name: String, 
    description: Option[String] = None, 
    createdAt: Option[DateTime: = None, 
) 

class UserTable(tag: Tag) extends Table[User](tag, "user") { 
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc) 
    def accountId = column[Long]("account_id") 
    def name = column[String]("name") 
    def description = column[Option[String]]("description") 
    def createdAt = column[Option[DateTime]]("created_at") 
    def * = (id.?, accountId, name, description, createdAt) <> (User.tupled, User.unapply) 
} 

object Users extends TableQuery(new UserTable(_)) { 
} 

val user = User(None, accountId, name, description) 
val insert = for { 
    newId <- (Users returning Users.map(_.id)) += user 
} yield newId 

db.run(insert) 

生成されたSQL

[debug] s.j.J.statement - Preparing insert statement (returning: id): insert into `user` (`account_id`,`name`,`description`,`created_at`) values (?,?,?,?) 

[debug] s.j.J.parameter - /------+--------+---------+-----------\ 
[debug] s.j.J.parameter - | 1 | 2  | 3  | 4   | 
[debug] s.j.J.parameter - | Long | String | VARCHAR | TIMESTAMP | 
[debug] s.j.J.parameter - |------+--------+---------+-----------| 
[debug] s.j.J.parameter - | 1 | user01 | NULL | NULL  | 
[debug] s.j.J.parameter - \------+--------+---------+-----------/ 

答えて

1

あなたの例を再考。あなたのテーブルは、列created_atの値としてnullを受け入れません。しかし、ドメインモデルでは、このフィールドはnull以外の方法でデータベースに表現することができないNoneにすることができます。したがって、正確なクエリを生成するには、created_atのタイプをDateTimeに変更する必要があります。

+0

このようにして、挿入するUserインスタンスを作成するための 'User(None、accountId、name、description、new DateTime())'と表の修飾子 'DEFAULT CURRENT_TIMESTAMP'滑らかに使用されることはありませんか? – xfan

+0

あなたのケースでは、はい、使用されていません。それはあなたが今私は知らない方法でそれを実装することが可能かどうか。これを読むことを検討してください: http://slick.lightbend.com/doc/3.0.0/queries.html#inserting テーブル定義でデフォルト値を達成することは可能ですが、わかりません –

0

createdAtOptionであることはできません。Optionの使用を避けるためにDateTime.nowを置くことができます。

implicit def dateTime = 
     MappedColumnType.base[DateTime, Timestamp](
     dt => new Timestamp(dt.getMillis), 
     ts => new DateTime(ts.getTime) 
) 

そして、あなたはDateTime.nowに対処したくない場合は、あなたのような何かを行うことがあります。

import slick.lifted.MappedTypeMapper 
import java.sql.Date 
import org.joda.time.DateTime 
import slick.lifted.TypeMapper.DateTypeMapper 

object DateTimeMapper { 
    implicit def date2dt = MappedTypeMapper.base[DateTime, Date] (
    dt => new Date(dt.getMillis), 
    date => new DateTime(date) 
) 
} 

それとも、おそらくDateTimestampのためにそれをない必要があります。またDateTime列マッパーが必要ですこの:ここ

def created = column[DateTime]("createdAt", SqlType("timestamp not null default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP")) 

追加情報: http://queirozf.com/entries/scala-slick-dealing-with-datetime-timestamp-attributes

0

あなたの投影を見ると、IDを持ち上げるのと同じように、created_atを持ち上げなければなりません。

だからあなたの投影がなる:

def * = (id.?, accountId, name, description, createdAt.?) <> (User.tupled, User.unapply)

createdAt後.?に注意してください。

関連する問題