我有一个简单的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,但它没有帮助。
答案 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
}
现在架构已创建,数据已添加到数据库中。