ScalaQuery 和 Play 框架:处理未分配 (AutoInc) 主键的最佳实践

Posted

技术标签:

【中文标题】ScalaQuery 和 Play 框架:处理未分配 (AutoInc) 主键的最佳实践【英文标题】:ScalaQuery and Play framework: Best practice for handling unassigned (AutoInc) primary keys 【发布时间】:2012-07-29 15:58:46 【问题描述】:

我正在使用 Play 2.0.2 和 ScalaQuery 0.9.5。

我有以下简单的模型代码:

case class Task(id: Long, name: String)

object Task extends Table[(Long, String)]("task") 

lazy val database = Database.forDataSource(DB.getDataSource())

def id = column[Long]("id", O PrimaryKey, O AutoInc)
def name = column[String]("name", O NotNull)

def create(task: Task) = database.withSession 
  implicit db: Session => 
    Task.name insert(task.name)
  

以及以下处理表单提交的代码:

val taskForm: Form[Task] = Form(
  mapping(
    "name" -> nonEmptyText
  ) 
    (name) => Task(-1L, name)
   
    task => Some(task.name)
  
)

def newTask = Action 
  implicit request =>
    taskForm.bindFromRequest.fold(
      errors => BadRequest(views.html.index(Task.all, errors)),
      task => 
        Task.create(task)
        Redirect(routes.Application.tasks())
      
    )

几个问题:

1) 有没有比传入常量更好的方法来处理瞬态主键值?类似于 Anorm 的 NotAssigned 的东西?

2) 将“id”->ignore(-1L) 添加到表单映射并使用任务的提取器函数会更好吗?

3) 是否应该在没有 id 字段的情况下定义案例类?

【问题讨论】:

【参考方案1】:

如果Task 有一个 id,你不应该使用这个类来表示一个没有 id 的值(目前)。无论如何,创建的对象通常包含与表单中填写的数据不同的数据(例如创建日期等),因此使用相同的类通常没有意义来表示所需的值创建一个对象和创建的对象本身。

所以你可以定义另一个案例类,例如TaskForm(最终可能继承自 Task 的公共基础),或者,在您的情况下,只需使用产生 String 值的表单:

// Task
case class Task(id: Long, name: String)

object Task extends Table[(Long, String)]("task") 
  lazy val database = Database.forDataSource(DB.getDataSource())

  def id = column[Long]("id", O PrimaryKey, O AutoInc)
  def name = column[String]("name", O NotNull)

  def create(name: String) = database.withSession  implicit db: Session =>
    Task.name insert(name)
  



// Application
object Application extends Controller 
  val taskForm = Form("name" -> nonEmptyText)
  def newTask = Action  implicit request =>
    taskForm.bindFromRequest.fold(
      errors => BadRequest(views.html.index(Task.all, errors)),
      name => 
        Task.create(name)
        Redirect(routes.Application.tasks())
      
    )
  

【讨论】:

以上是关于ScalaQuery 和 Play 框架:处理未分配 (AutoInc) 主键的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Play框架下处理致命错误的正确方法

使用 Play 框架的 REST URL 错误处理

play框架使用起来(12)

Play 框架中的请求队列

play框架使用起来(12)

Java8 Try-with-resource/JDBC/Play 框架:这是正确的吗?