You can change the signatures to take an implicit connection and then control the transaction outside the create methods.
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()
}
}
As you can see in the WebsiteList
I changed the DB.withConnection
to DB.withTransaction
since you are doing several inserts and want them committed together in the same transaction.
This lets you control when and where the Connection
should be shared.
For example you could do the transaction management in the controller which knows better for how long a transaction should be used:
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) {
}
}