anormでNULLを許容するテーブルをSelectする
scala初心者、playframeworkも初心者な私が触ってみてはまったことを解説していく。
playframeworkのチュートリアルをやってみて、ちょっと変更しようと思ったら「Null列がSelectできないでござる」とか言われてしまった。
チュートリアル:http://www.playframework.org/documentation/2.0/ScalaTodoList
例えば、タスクの情報に"登録日"(createdate)と"締切日"(deadline)を追加したい。
チュートリアルで作成した1.sqlを改良して、列を追加する。
# Tasks schema # --- !Ups CREATE SEQUENCE task_id_seq; CREATE TABLE task ( id integer NOT NULL DEFAULT nextval('task_id_seq'), label varchar(255), deadline date, createdate date DEFAULT sysdate ); # --- !Downs DROP TABLE task; DROP SEQUENCE task_id_seq;
登録日はinsertした日でいいのでDEFAULT sysdate。
次にmodels/Task.scalaを修正。
case classの部分と、
case class Task( id: Long, label: String, deadline: Date, createdate: Date )
val taskを変更。
val task ={ get[Long]("id") ~ get[String]("label") ~ get[Date]("deadline") ~ get[Date]("createdate") map { case id~label~deadline~createdate => Task(id,label,deadline,createdate) } }
val taskってのはSQLの結果をパースするParserを変数にしている。
チュートリアルでは、SQL("select * from task").as(task *) と書いている。
そしてviewも変更する。
チュートリアルをちょっと変更してtableでタスク一覧を表示する。
index.scala.html
@(tasks: List[Task], taskForm: Form[String]) @import helper._ @main("Todo List") { <h1>@tasks.size task(s)</h1> <table border="1"> <tr> <td>ID</td> <td>タスク</td> <td>締切日</td> <td>登録日</td> </tr> @tasks.map { task => <tr> <td>@task.id</td> <td>@task.label</td> <td>@task.deadline</td> <td>@task.createdate</td> <td> @form(routes.Application.deleteTask(task.id)) { <input type="submit" value="Delete"> } </td> </tr> } </table> <h2>Add a new task</h2> @form(routes.Application.newTask) { @inputText(taskForm("label")) <input type="submit" value="Create"> } }
これでタスクを登録してみると・・・
insertは成功して、再表示のTask.all()メソッドでエラーです。
[RuntimeException: UnexpectedNullableFound(TASK.DEADLINE)]
deadlineがNULLなので型が解析できないようです。
Optionを使ってNULLを許容できるようにしてあげます。
case class Task( id: Long, label: String, deadline: Option[Date], createdate: Date ) object Task { val task ={ get[Long]("id") ~ get[String]("label") ~ get[Option[Date]]("deadline") ~ get[Date]("createdate") map { case id~label~deadline~createdate => Task(id,label,deadline,createdate) } } 〜〜〜
これでおっけー!
こう見ると単純で簡単なんだけど、scala初心者には
SQLParserってなにこれどう動くのとか、case classにもOption必要なの?とか
ハマりどころだったわけです。
まずはScalaをじっくり学んだほうが良さそうですな。
おわり!