无法使用 Play for Scala 和 Anorm 从表单中插入值

Cannot insert values from form using Play for Scala and Anorm

当我在表单字段中输入数据并单击 "Add book" 按钮时,没有任何反应...输入到字段中的数据并没有添加到数据库中,我没有收到任何错误,我也不知道我做错了什么...

我有以下控制器

package controllers
import play.api.data.Form
import play.api.data.Forms._
import play.api.mvc.{Action, Controller}
import anorm.NotAssigned
import play.api.Play.current
import play.api.i18n.Messages.Implicits._
import models.Buch

object Book extends Controller{

 val addBookForm = Form(
     mapping(
         "name" -> nonEmptyText,
         "author" -> nonEmptyText,
         "category" -> nonEmptyText,
         "read" -> boolean,
         "amount" -> number
     )(Buch.apply)(Buch.unapply)
 )  

 def add = Action {
     Ok(views.html.book(addBookForm))
 }


 def addBuch() = Action { implicit request =>
  addBookForm.bindFromRequest.fold(
    errors => BadRequest,
    {
      case Buch(name, author, category, read, amount) =>
      Buch.addBook(Buch(name, author, category, read, amount))
      Ok("Book successfully added!")

     }
    )
   }
 }

以下型号

 package models

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

 import anorm._
 import anorm.SqlParser._

 case class Buch(name:String, author:String, category:String, read:Boolean, amount: Int)

 object Buch{

     val simple = {
         get[String]("buch.name") ~
         get[String]("buch.auhtor") ~
         get[String]("buch.category") ~
         get[Boolean]("buch.read") ~
         get[Int]("buch.amount") map {
       case name~author~category~read~amount => Buch(name, author, category, read, amount)
       }
     }

def findAll(): Seq[Buch] = {
   DB.withConnection { implicit connection =>
     SQL("select * from buch").as(Buch.simple *)
   }
}

def addBook(buch:Buch): Unit = {
   DB.withConnection { implicit connection =>
     SQL("insert into buch(name, author, category, read, amount) values ({name}, {author}, {category}, {read}, {amount})").on(
       'name -> buch.name,
       'author -> buch.author,
       'category -> buch.category,
       'read -> buch.read,
       'amount -> buch.amount
    ).executeUpdate()
  }
 }
}

以下sql脚本

  # Buch schema

  # --- !Ups

  CREATE TABLE Buch (
      id bigint(20) NOT NULL AUTO_INCREMENT,
      name varchar(255) NOT NULL,
      author varchar(255) NOT NULL,
      category varchar(255) NOT NULL,
      read boolean NOT NULL DEFAULT '0',
      amount int(11) NOT NULL,
      PRIMARY KEY (id)
  );


  # --- !Downs

  DROP TABLE Buch;

以下观点

  @(form: Form[Buch])(implicit messages: Messages)

  @main("Welcome to Play 2.0") {

  @helper.form(action = routes.Book.addBuch) {
       @helper.inputText(form("name"))
       @helper.inputText(form("author"))
       @helper.inputText(form("category"))
       @helper.inputText(form("read"))
       @helper.inputText(form("amount"))
       <input type="submit" value="Add book"/>
   }

 }

如果我修改模型,例如仅使用 3 个参数创建它,名称、作者和类别,方法 addBook 会将数据插入我的数据库。

谁能告诉我我做错了什么?

谢谢!

在mysql中,read是保留字。参见 docs

CREATE TABLE Buch (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  name varchar(255) NOT NULL,
  author varchar(255) NOT NULL,
  category varchar(255) NOT NULL,
  read boolean NOT NULL DEFAULT '0',  
  amount int(11) NOT NULL,
  PRIMARY KEY (id)
);

你应该用一些非保留词替换它(例如 book_read)或者通过像这样放入反引号来转义它:

CREATE TABLE Buch (
  id bigint(20) NOT NULL AUTO_INCREMENT,
  name varchar(255) NOT NULL,
  author varchar(255) NOT NULL,
  category varchar(255) NOT NULL,
  `read` boolean NOT NULL DEFAULT '0',
  amount int(11) NOT NULL,
  PRIMARY KEY (id)
);

编辑:

Anorm 不提供从 mysql 布尔值到 scala 布尔值的默认映射。从它的 documentation:

It’s possible to add custom mapping, for example if underlying DB doesn’t support boolean datatype and returns integer instead. To do so, you have to provide a new implicit conversion for Column[T], where T is the target Scala type:

import anorm.Column

// Custom conversion from JDBC column to Boolean
implicit def columnToBoolean: Column[Boolean] = 
  Column.nonNull1 { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case bool: Boolean => Right(bool) // Provided-default case
      case bit: Int      => Right(bit == 1) // Custom conversion
      case _             => 
       Left(TypeDoesNotMatch(s"Cannot convert $value: ${value.asInstanceOf[AnyRef].getClass} to Boolean 
 for column $qualified"))
    }
  }

另请参阅 this discussion 关于 Anorm - Mysql 布尔值。