Scala,播放 - 无法插入 Postgresql 数据库

Scala, play - cannot insert into Postgresql database

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

我在 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"

Table 定义和 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)
  }

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

编辑:

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);

这是我用来手动创建 table 的脚本,然后我尝试将数据 frm 请求保存到数据库中。从请求中读取一切正常(创建对象产品)但没有数据仍然安全地进入数据库。

编辑 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,但它没有帮助。

默认在控制器中异步播放动作。所以渲染在调用数据库完成之前完成。调用数据库是一个缓慢的操作,这被认为是副作用:网络 + 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 添加(产品:产品):未来 [Int] = { val 操作 = 产品 += 产品

   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 )

}

终于成功了。我将添加功能更改为:

 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
  }

现在模式已创建,数据已添加到数据库中。