7

Давайте предположим, что у меня есть следующие методы:
Об одном WebsitesList модели:О сделках и вложенная DB пишет (с помощью Scala)

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

As вы можете видеть, я запускаю транзакцию по методу создания веб-сайтов, и указанный метод вызывает метод создания модели веб-сайта.
Моя цель - удалить созданные записи веб-сайтов, если по какой-либо причине не удалось создать веб-сайт. Чтобы протестировать его, я создаю исключение и, как и ожидалось, записи WebsitesList и List не создаются. Тем не менее, записи веб-сайтов не отменены после исключения и остаются в базе данных.

Моя теория заключается в том, что метод Website.create создал новое соединение вместо существующего. Кто-нибудь знает, как я могу это исправить?

Спасибо.

ответ

11

Вы можете изменить подписи, чтобы принять неявное соединение, а затем управлять транзакцией вне методов 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.withConnection к DB.withTransaction, так как вы делаете несколько вставок и хотите, чтобы они совершили вместе в одной и той же сделки ,

Это позволяет вам контролировать, когда и где должно быть предоставлено сообщение Connection.

Например, вы могли бы сделать управление транзакциями в контроллер, который знает лучше, как долго следует использовать транзакции:

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) { 
    } 
} 
+0

где объект SQL находится? –

+0

@Alex 'anorm.SQL' – maba

+0

Что такое пакет Connection? – RafaelTSCS

Смежные вопросы