gpt4 book ai didi

playframework - 关于事务和嵌套数据库写入(使用 Scala)

转载 作者:行者123 更新时间:2023-12-04 03:38:18 24 4
gpt4 key购买 nike

假设我有以下方法:
在网站列表模型上:

def create(urls: List[String]) = DB.withTransaction(implicit c => {
val websites = urls.map(Website.create(_))
val listId: Option[Long] = SQL("INSERT INTO LIST (created_date, active) VALUES ({created_date}, {active})").
on('created_date -> new Date(), 'active -> true).
executeInsert()
websites.foreach(websiteId =>
SQL("INSERT INTO websites_list (list_id, website_id) VALUES ({listId}, {websiteId})").
on('listId -> listId.get, 'websiteId -> websiteId.id).executeInsert()
)

throw new Exception()
})

在网站模型上:
def create(url: String): Website = DB.withConnection {
implicit c =>
val currentDate = new Date()
val insertedId: Option[Long] = SQL("insert into websites (url, Date_Added) values ({url}, {date})").
on('url -> url, 'date -> currentDate).
executeInsert()
Website(insertedId.get, url, currentDate)
}

如您所见,我在 WebsitesList create 方法上启动了一个事务,该方法调用了 Website 模型的 create 方法。
如果由于某种原因无法创建网站列表,我的目标是删除创建的网站记录。为了测试它,我提出了一个异常,正如预期的那样,没有创建 WebsitesList 和 List 记录。但是,网站记录不会在异常发生后回滚并保留在数据库中。

我的理论是 Website.create 方法创建了一个新连接,而不是使用现有连接。有谁知道我该如何解决这个问题?

谢谢。

最佳答案

您可以更改签名以采用隐式连接,然后在 create 方法之外控制事务。
Website.scala

object Website {

def create(url: String): Website = {
DB.withConnection { implicit connection =>
createWithConnection(url)
}
}

def createWithConnection(url: String)(implicit connection: Connection): Website = {
val currentDate = new Date()
val insertedId: Option[Long] = SQL("insert into websites(url, Date_Added) values ({url}, {date})").
on('url -> url, 'date -> currentDate).
executeInsert()
Website(insertedId.get, url, currentDate)
}
}
WebsiteList.scala
object WebsiteList {

def create(urls: List[String]) = DB.withTransaction(implicit c => {
createWithConnection(urls)
})

def createWithConnection(urls: List[String])(implicit connection: Connection) = {
val websites = urls.map(Website.createWithConnection)
val listId: Option[Long] = SQL("INSERT INTO LIST (created_date, active) VALUES ({created_date}, {active})").
on('created_date -> new Date(), 'active -> true).
executeInsert()
websites.foreach(websiteId =>
SQL("INSERT INTO websites_list (list_id, website_id) VALUES ({listId}, {websiteId})").
on('listId -> listId.get, 'websiteId -> websiteId.id).executeInsert()
)

throw new Exception()
}
}

正如您在 WebsiteList 中看到的那样我换了 DB.withConnectionDB.withTransaction因为您正在执行多个插入并希望它们在同一个事务中一起提交。

这让您可以控制 Connection 的时间和地点应该共享。

例如,您可以在 Controller 中进行事务管理,它更清楚应该使用多长时间的事务:

object SomeController extends Controller {
def someAction(someData: String) = Action { implicit request =>
DB.withTransaction { implicit connection =>
SomeModel.create(someData)
OtherModel.create(someData)
}
}
}

object SomeModel {
def create(data: String)(implicit connection: Connection) {
}
}

object OtherModel {
def create(data: String)(implicit connection: Connection) {
}
}

关于playframework - 关于事务和嵌套数据库写入(使用 Scala),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18755045/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com