【问题标题】:Cannot insert values from form using Play for Scala and Anorm无法使用 Play for Scala 和 Anorm 从表单中插入值
【发布时间】:2015-10-04 11:32:31
【问题描述】:

当我在表单字段中输入数据并单击“添加书籍”按钮时,它什么也没有发生...输入的数据没有添加到数据库中,我没有收到错误,我不知道我是什么我做错了...

我有以下控制器

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 会将数据插入到我的数据库中。

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

谢谢!

【问题讨论】:

  • 添加调试以检查是否调用了addBook。如果是,请尝试在您的数据库客户端中执行具有相同值的插入以检查会发生什么。据此,您可以获得更多帮助。
  • 看来我的模型(我认为)没有“看到”布尔数据类型......所以这就是它不起作用的原因......我把它改成了 varchar 现在输入来自表单存储在我的数据库中。
  • 这些类型,BOOL 和 BOOLEAN 是 TINYINT(1) 的同义词。零值被认为是错误的。

标签: mysql forms scala playframework-2.0


【解决方案1】:

在 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 boolean 到 scala boolean 的默认映射。来自其documentation

可以添加自定义映射,例如,如果底层数据库 不支持布尔数据类型,而是返回整数。去做 因此,您必须为 Column[T] 提供一个新的隐式转换,其中 T 是目标 Scala 类型:

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"))
    }
  }

另请参阅 Anorm - Mysql Boolean 上的 this discussion

【讨论】:

  • 感谢您的回答,但它没有用...我按照您所说的替换了保留的书,但没有...我注意到如果我将 book_read 的类型修改为 String 例如,它有效,但对于布尔值则无效。为什么会这样?谢谢!
  • @Hkt anorm 文档提供了有关如何在不支持布尔类型的数据库中使用布尔类型的信息。编辑了相同的答案。
猜你喜欢
  • 2013-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-13
  • 2014-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多