【问题标题】:Play! Framework/Anorm: Converting data to JSON and storing into DB玩!框架/异常:将数据转换为 JSON 并存储到数据库中
【发布时间】:2016-04-14 03:22:43
【问题描述】:

第一次使用 play 框架,我正在努力将已转换为 JSON 的数据保存到我在框架中建立的数据库中。

这是我正在尝试的:

Controller:

//Write converter to convert our model data to JSON
implicit val taskWrites: Writes[Task] = (
    (JsPath \ "id").write[Int] and
    (JsPath \ "name").write[String] and
    (JsPath \ "description").write[String] and
    (JsPath \ "group").write[String]
    )(unlift(Task.unapply))



//saving tasks in JSON format. Returning OK if success.
def saveTask = Action(BodyParsers.parse.json) { request =>
    val taskResult = request.body.validate[Task]
    taskResult.fold(
        errors => {
            BadRequest(Json.obj("status" -> "KO", "Message" -> JsError.toJson(errors)))
        },
        task => {
            Task.save(task)
            //ERROR HERE: Task.insertIntoDB(task)
            Ok(Json.obj("status" -> "Ok", "Message" -> ("Task '" +task.name+ "' saved")))
        }
    )
}

Model:

case class Task(id: Int, name: String, description: String, group: String)

var list: List[Task] = Nil

//define a parser that will transform a JDBC ResultSet into a Task value.
val task = {
    get[Int]("id") ~
    get[String]("name") ~
    get[String]("description") ~
    get[String]("group") map {
        case id~name~description~group => Task(id, name, description, group)
    }

}

def save(task: Task) = {
    list = list ::: List(task)
}

def insertIntoDB(task: Task){
    DB.withConnection { implicit c =>
        SQL("insert into task (id, name, description, groupname) values ({task.id, task.name, task.description, task.group})").on(
            'id -> task.id,
            'name -> task.name,
            'description -> task.description,
            'groupname -> task.group
            ).executeUpdate()
    }
}

我正在使用 H2 数据库引擎

evolutions/default/1.sql:

#Tasks Schema

# ---- !Ups
CREATE SEQUENCE task_id_seq;
CREATE TABLE task (
    id integer NOT NULL DEFAULT nextval('task_id_seq'),
    name varchar(255),
    description varchar(255),
    groupname varchar(255)
);

# ---- !Downs
DROP SEQUENCE task_id_seq;
DROP TABLE task;

但是当我尝试添加新任务时:

curl --include --request POST --header "content-type: application/json" --data '{"id":4, "name": "test5", "description": "testdesc1","group": "groupc"}' http://localhost:9000/tasks

我收到错误消息:

[JdbcSQLException: Syntax error in SQL statement "INSERT INTO TASK (ID, NAME, DESCRIPTION, GROUPNAME) VALUES ( [*]"; expected "), DEFAULT, NOT, EXISTS, INTERSECTS"; SQL statement: insert into task (id, name, description, groupname) values ( [42001-191]]

我这样做是否正确?忽略错误,我不这么认为。如何结合save 和insertIntoDB?

另外,我怎样才能测试添加数据而不必每次都卷曲?

感谢您的帮助!

编辑:添加架构 + 新错误

【问题讨论】:

  • 您确定task 表有name 列吗?您可以成功地将插入直接运行到数据库中吗?您使用的是哪个数据库?
  • 好的。射击。我觉得很笨。我刚刚检查了一下,我的“名称”列被标记为“标签”。我修复了它,但现在我遇到了一个新错误。我会更新我的问题

标签: json scala playframework anorm


【解决方案1】:

问题是您在插入时使用了错误的名称/键:

您的代码:

def insertIntoDB(task: Task) {
  DB.withConnection { implicit c =>
    SQL("insert into task (id, name, description, groupname) values ({task.id, task.name, task.description, task.group})").on(
      'id -> task.id,
      'name -> task.name,
      'description -> task.description,
      'groupname -> task.group
    ).executeUpdate()
  }
}

问题是:

  1. 插入模板错误。假设每个变量使用{}
  2. 模板中使用的键 (task.id) 与 on (id) 中使用的键不匹配

你可以改写成:

def insertIntoDB(task: Task) {
  DB.withConnection { implicit c =>
    SQL("insert into task (id, name, description, groupname) values ({id}, {name}, {description}, {groupname})").on(
      'id -> task.id,
      'name -> task.name,
      'description -> task.description,
      'groupname -> task.group
    ).executeUpdate()
  }
}

或者甚至可以缩写为:

def insertIntoDB(task: Task) {
  DB.withConnection { implicit c =>
    SQL("insert into task (id, name, description, groupname) values (${task.id}, ${task.name}, ${task.description}, ${task.group})").executeUpdate()
  }
}

我强烈建议您阅读此处的 Anorm 文档:

https://www.playframework.com/documentation/2.5.x/ScalaAnorm

【讨论】:

  • 啊!我没有意识到每个变量都需要{ }。我想我可以通过阅读文档来节省很多时间来写出这个问题。但是在修改我的代码后,我遇到了另一个错误:[MissingParameter: Missing parameter value after: StringToken(insert into task (id, name, description, groupname) values ($)]
  • 我已经更正了答案。模板 (group) 和参数 (groupname) 不匹配。
  • 完美!是的!有用。非常感谢您的帮助。
  • @MikeHenke 在我看来,最好的方法是编写自动化测试。为了熟悉 Play 中的测试支持,您应该阅读以下文档部分:Testing your application 和 Testing your application with ScalaTest。 curl 测试更像是手动测试,它们作为最后的门检查很好,但它们也经常运行成本很高(因为,它们都是手动的)。
  • SQL("insert into task (id, name, description, groupname) values (${task.id}, ${task.name}, ${task.description}, ${task.group})") 是错误的,它既不是普通的 Scala 插值,也不是 Anorm SQL 插值。使用 Anorm 占位符:SQL("... {placeholder} ...").on("placeholder" -> value) 或 SQL"... $value ..."(SQL 和字符串之间没有 (,如 s"foo $value")。
猜你喜欢
  • 1970-01-01
  • 2012-07-29
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2018-12-24
  • 1970-01-01
相关资源
最近更新 更多