Scala,play - 无法插入Postgresql数据库

时间:2017-05-27 11:47:58

标签: database postgresql scala playframework slick

我有一个简单的scala和播放代码,用于将产品插入数据库。

我在application.conf中的数据库配置如下所示:

db.default.hikaricp.connectionTestQuery = "SELECT 1"

db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://localhost:5432/shop"
db.default.user="postgres"
db.default.password="root"

表定义和crud操作:

case class Product(id: Long, name: String, description: String, price: BigDecimal, amount: Int)

case class ProductFormData(name: String, description: String, price: BigDecimal, amount: Int)

object ProductForm {

  val form = Form(
    mapping(
      "name" -> nonEmptyText,
      "description" -> nonEmptyText,
      "price" -> bigDecimal,
      "amount" -> number
    )(ProductFormData.apply)(ProductFormData.unapply)
  )
}

class ProductTableDef(tag: Tag) extends Table[Product](tag, "product") {

  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)

  def name = column[String]("name")

  def description = column[String]("description")

  def price = column[BigDecimal]("price")

  def amount = column[Int]("amount")

  override def * =
    (id, name, description, price, amount) <> (Product.tupled, Product.unapply)
}

object Products {

  val products = TableQuery[ProductTableDef]

  private def db: Database = Database.forDataSource(DB.getDataSource())

  def add(product: Product): Future[Int] = {
    try db.run(products += product)
    finally db.close
  }

  def delete(id: Long): Future[Int] = {
    db.run(products.filter(_.id === id).delete)
  }

  def get(id: Long): Future[Option[Product]] = {
    db.run(products.filter(_.id === id).result.headOption)
  }

  def listAll: Future[Seq[Product]] = {
    db.run(products.result)
  }
}

服务:

object ProductService {
  def addProduct(product: Product): Future[Int] = {
    Products.add(product)
  }
}

和控制器:

def create() = Action(parse.json) { request =>
    val name = (request.body \ "name").as[String]
    val description = (request.body \ "description").as[String]
    val price = (request.body \ "price").as[BigDecimal]
    val amount = (request.body \ "amount").as[Int]

    val product = Product(0, name, description, price, amount)
    ProductService.addProduct(product)

    Ok("name : " + product.name)
  }

一切看起来都不错,过程中没有错误(我使用postman,创建json并将其发送到服务器)。但毕竟数据库中没有数据。甚至表也不是在数据库中创建的。我真的不知道为什么这不能添加到数据库。

修改

create table "Product" ("id" BIGSERIAL NOT NULL PRIMARY KEY,"name" VARCHAR(254) NOT NULL,"description" VARCHAR(254) NOT NULL,"price" Decimal, "amount" BIGINT NOT NULL);

这是我用来手动创建表的脚本,然后我尝试将数据请求保存到数据库中。从请求开始,所有内容都可以正常读取(对象产品已创建),但数据库中仍然没有数据安全。

编辑2:

case class Product(id: Option[Long], name: String, description: String, price: BigDecimal, amount: Int)

class ProductTableDef(tag: Tag) extends Table[Product](tag, "product") {

  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)

  def name = column[String]("name")

  def description = column[String]("description")

  def price = column[BigDecimal]("price")

  def amount = column[Int]("amount")

  override def * =
    (id.?, name, description, price, amount) <> (Product.tupled, Product.unapply)
}

我使用选项自动增量字段更新了模型和dao,但它没有帮助。

2 个答案:

答案 0 :(得分:2)

默认情况下,在控制器异步中播放操作。所以在调用数据库之前完成渲染。调用数据库是一个缓慢的操作,这被认为是副作用:网络+ IO操作。 检查这个的简单方法是在渲染之前放置下一个代码:

 Thread.sleep(2000)

你实际应该做的是:

def add = Action.async( parse.json(userReads) ) { request =>
    val results = userRepo.insert(  UserData( None, request.body.name, request.body.note ) )
    results.map(_ => Ok("done") )

要创建所需的表,您应该使用以下内容:

val setup = DBIO.seq(
  // Create the tables, including primary and foreign keys
  (suppliers.schema ++ coffees.schema).create,


  //
)

val setupFuture = db.run(setup)

这是一个灵活的api文档:http://slick.lightbend.com/doc/3.0.0/gettingstarted.html#schema

不确定您是否会将此逻辑放在webApp

尝试查看Slick生成的SQL:

相应地更新您的方法  def add(产品:产品):Future [Int] = {     val action = products + = product

   val sql = action.result.statements.toString()

   // this is SQL query which slick will try run against postGreed 
   // you should be able to run it manually from SQL console to see reason why this failing 
   println(sql)

db.run( action )

}

答案 1 :(得分:2)

最后它有效。我将添加功能更改为:

 def add(product: Product): Unit = {
    try {
      Await.result(db.run(DBIO.seq(
        products.schema.create,
        products += (product),
        products.result.map(println))), Duration.Inf)
    } finally db.close
  }

现在架构已创建,数据已添加到数据库中。