jpersson / prequel

because SQL is a pretty good abstraction already
55 stars 31 forks source link

transaction management across several DAOs #16

Open vatel opened 11 years ago

vatel commented 11 years ago

I think in some cases it is handy to manage transactions from outside of DAO objects, ex:

class MyBusinessLogic {

def doSomething = {

inTransaction { dao1.create dao2.update ... }

}

I have implemented this functionality for prequel (in a separate class, without patching in fact) and can share it here, Sorry, I am not experienced with github yet, so I could send it to email or post here, just let me know.

jpersson commented 11 years ago

If you want use multiple DAOs within out transaction you have to pass the connection to the DAO instance somehow. Either through the method itself or the constructor.

vatel commented 11 years ago

let me explain a little bit:

Here are that new classes (just fragments):

// to be use in business logic (ie at more high level)
trait TransactionManager {
  def inTransaction[T](block: => T): T
}
// to be used in DAOs
class DatabaseTransactionManager(val db: DatabaseConfig) extends TransactionManager {
def transaction[T](block: (Transaction) => T): T = {...}
override def inTransaction[T](block: => T): T = {
    transaction { tr =>
      block
    }
}

and how I use them:

// this class itself does NOT work with database
class BusinessLogic(
  implicit val dao: SomeDAO,
  implicit val tm: TransactionManager)  {
import tm._
def doSomething = {
  // call DAO method in the same transaction
  inTransaction {
      dao.createSomethin(...)
      dao.updateSomething(...)
      dao.doSomethingElse(...)
  }
}
}
class SomeDAO (implicit tm: DatabaseTransactionManager) {
import tm._
def createSomethin(...) = {
    transaction { tx =>
        tx.execute("insert into ..."...)
    }
}
...
}

DatabaseTransactionManager class implements thread-local stack of currently-running transactions, so the example above executes in the same transaction. I have also added support for 'REQUIRES_NEW' propagation semantic. It works both with one and multiple DAOs inside transaction.

vatel commented 11 years ago

So the issue in fact is about more complicated use-cases of transaction management - when you can do several things (from multiple DAO methods or multiple DAOs) inside the same transaction and you do not want to write heavyweight methods in DAO.