2013-07-19 27 views
0

我知道evolution是在開發模式下自動應用的。我的問題是,我如何產生演變?我如何生成與它們相對應的模型?我目前面臨很多打字輸入一個簡單的模型。它不是乾的,有很多樣板。這似乎與Play的文化背道而馳。在Play 2中生成演化和模型的正確方法是什麼?

這是我面對打字的代碼,有什麼更好的辦法?:

1.SQL: #---首先數據庫架構

# --- !Ups 

create table task (
    id      bigint not null primary key, 
    title      varchar(255) not null, 
    done      boolean, 
    due_date     timestamp, 
    assigned_to    varchar(255), 
    project     bigint not null, 
    folder     varchar(255), 
    foreign key(assigned_to) references user(email) on delete set null, 
    foreign key(project)  references project(id) on delete cascade 
); 

# --- !Downs 

drop table if exists task; 

Task.scala:

package models 

import java.util.{Date} 

import play.api.db._ 
import play.api.Play.current 

import anorm._ 
import anorm.SqlParser._ 

case class Task(id: Pk[Long], folder: String, project: Long, title: String, done: Boolean, dueDate: Option[Date], assignedTo: Option[String]) 

object Task { 

    // -- Parsers 

    /** 
    * Parse a Task from a ResultSet 
    */ 
    val simple = { 
    get[Pk[Long]]("task.id") ~ 
    get[String]("task.folder") ~ 
    get[Long]("task.project") ~ 
    get[String]("task.title") ~ 
    get[Boolean]("task.done") ~ 
    get[Option[Date]]("task.due_date") ~ 
    get[Option[String]]("task.assigned_to") map { 
     case id~folder~project~title~done~dueDate~assignedTo => Task(
     id, folder, project, title, done, dueDate, assignedTo 
    ) 
    } 
    } 

    // -- Queries 

    /** 
    * Retrieve a Task from the id. 
    */ 
    def findById(id: Long): Option[Task] = { 
    DB.withConnection { implicit connection => 
     SQL("select * from task where id = {id}").on(
     'id -> id 
    ).as(Task.simple.singleOpt) 
    } 
    } 

    /** 
    * Retrieve todo tasks for the user. 
    */ 
    def findTodoInvolving(user: String): Seq[(Task,Project)] = { 
    DB.withConnection { implicit connection => 
     SQL(
     """ 
      select * from task 
      join project_member on project_member.project_id = task.project 
      join project on project.id = project_member.project_id 
      where task.done = false and project_member.user_email = {email} 
     """ 
    ).on(
     'email -> user 
    ).as(Task.simple ~ Project.simple map { 
     case task~project => task -> project 
     } *) 
    } 
    } 

    /** 
    * Find tasks related to a project 
    */ 
    def findByProject(project: Long): Seq[Task] = { 
    DB.withConnection { implicit connection => 
     SQL(
     """ 
      select * from task 
      where task.project = {project} 
     """ 
    ).on(
     'project -> project 
    ).as(Task.simple *) 
    } 
    } 

    /** 
    * Delete a task 
    */ 
    def delete(id: Long) { 
    DB.withConnection { implicit connection => 
     SQL("delete from task where id = {id}").on(
     'id -> id 
    ).executeUpdate() 
    } 
    } 

    /** 
    * Delete all task in a folder. 
    */ 
    def deleteInFolder(projectId: Long, folder: String) { 
    DB.withConnection { implicit connection => 
     SQL("delete from task where project = {project} and folder = {folder}").on(
     'project -> projectId, 'folder -> folder 
    ).executeUpdate() 
    } 
    } 

    /** 
    * Mark a task as done or not 
    */ 
    def markAsDone(taskId: Long, done: Boolean) { 
    DB.withConnection { implicit connection => 
     SQL("update task set done = {done} where id = {id}").on(
     'id -> taskId, 
     'done -> done 
    ).executeUpdate() 
    } 
    } 

    /** 
    * Rename a folder. 
    */ 
    def renameFolder(projectId: Long, folder: String, newName: String) { 
    DB.withConnection { implicit connection => 
     SQL("update task set folder = {newName} where folder = {name} and project = {project}").on(
     'project -> projectId, 'name -> folder, 'newName -> newName 
    ).executeUpdate() 
    } 
    } 

    /** 
    * Check if a user is the owner of this task 
    */ 
    def isOwner(task: Long, user: String): Boolean = { 
    DB.withConnection { implicit connection => 
     SQL(
     """ 
      select count(task.id) = 1 from task 
      join project on task.project = project.id 
      join project_member on project_member.project_id = project.id 
      where project_member.user_email = {email} and task.id = {task} 
     """ 
    ).on(
     'task -> task, 
     'email -> user 
    ).as(scalar[Boolean].single) 
    } 
    } 

    /** 
    * Create a Task. 
    */ 
    def create(task: Task): Task = { 
    DB.withConnection { implicit connection => 

     // Get the task id 
     val id: Long = task.id.getOrElse { 
     SQL("select next value for task_seq").as(scalar[Long].single) 
     } 

     SQL(
     """ 
      insert into task values (
      {id}, {title}, {done}, {dueDate}, {assignedTo}, {project}, {folder} 
     ) 
     """ 
    ).on(
     'id -> id, 
     'folder -> task.folder, 
     'project -> task.project, 
     'title -> task.title, 
     'done -> task.done, 
     'dueDate -> task.dueDate, 
     'assignedTo -> task.assignedTo 
    ).executeUpdate() 

     task.copy(id = Id(id)) 

    } 
    } 

} 

回答

2

Ebean本身不支持DDL更改,因此使用自動演化只能從頭創建第一個DDL。

接下來的演變,你需要(字面上)編寫自己,包含所有的UP和DOWN,因此在開始時計劃初始DDL是非常重要的一步。

危險:由於您可能已經意識到自動創建的'scratch-evoulution'也會執行之前DDL的DOWN,這意味着您的所有數據都將丟失。

0

你的問題有兩個部分 - 演變和Scala模型。對於進化,大多數DB都有工具來爲你生成大部分SQL代碼(例如,在mysql工作臺中的「forward engineer」等等),有些會生成diff(alter/update)語句(例如mysql workbench的Synchronize Model)創造更容易的演變。

對於Scala模型,你可以看看Cato Crud generator。我已經根據自己的標準來調整模板,等等,他們肯定會提供一個開頭。

相關問題