Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to structure database access layer with transactions

I try to migrate application to Slick 3.0. I would like to make a transaction for Slick 3.0. I know how to do it but I would like to ask for classes structure. Please take a look on sample repositories:

Some repositories (or DAO) for Slick 2.1:

class UserRepository {
  def all()(implicit: Session): Seq[User] = users.run
  def insert(user: User)(implicit: Session): Int = users.insert(user)
  ...
}

class CarRepository {
  def all()(implicit: Session): Seq[Car] = cars.run
  def insert(car: Car)(implicit: Session): Int = cars.insert(car)
  ...
}

In order to do the transaction in Slick 2.1 I could create a service where I can do the transaction:

db.withTransaction{ implicit session =>
     userRepository.insert(user)
     carRepository.insert(car)
}

so currently I have repositories (or DAOs) for database access and services for more general logic.

Some repositories (or DAO) for Slick 3.0:

class UserRepository {
  def all(): Future[Seq[User]] = db.run(Users.result)
  def insert(user: User): Future[Int] = db.run(Users += user)

  ...
}

class CarRepository {
  def all(): Future[Seq[Car]] = db.run(Cars.result)
  def insert(car: Car): Future[Int] = db.run(Cars += car)
  ...
}

In Slick 3.0 we can do the transaction on DBIOActions but when we have the structure as shown above it is not possible because of futures. I could create some UserCarRepository class to do the transaction but I think it is not the best one. In order to overcome that situation I expose DBIOActions in repositories (or DAOs) and then in other layer mix DBIOActions from User and Car repositories in one transaction to return Future at the end (next layer could be a service to operate on futures). When we have more repositories for transaction it could like a little bit messy.

How to structure this for Slick 3.0? How to gain more loose coupling for the transaction on different repositories?

Reading: https://github.com/playframework/play-slick/tree/master/samples https://github.com/slick/slick/issues/1084 https://groups.google.com/forum/#!topic/scalaquery/32cO7lHbxOs

like image 703
piobab Avatar asked Jul 09 '15 16:07

piobab


People also ask

What should data access layer contain?

A data access layer (DAL) in computer software is a layer of a computer program which provides simplified access to data stored in persistent storage of some kind, such as an entity-relational database. This acronym is prevalently used in Microsoft environments.

How does a data access layer work?

A Data-Access Layer (DAL) can support multiple databases, so the application is able to make use of any database as per its requirement. Because segregating the data access code, enables better maintainability and easy migration of the database.

How do you create a data access layer using Entity Framework?

Select your project in the VS Solution Explorer window and press CTRL+SHIFT+A to add a new item. Search for the ADO.NET Entity Data Model item, then click “Add” to proceed. After the ADO.NET Entity Data Model component is added, it will automatically pop up its Data Model Wizard.


1 Answers

Keep the inserts as DBIOActions as long as possible, compose them as needed and then do the actual DB-query. Sketch:

class UserRepository {
  def all() = Users.result
  def insert(user: User) = Users += user

  ...
}

class CarRepository {
  def all() = Cars.result
  def insert(car: Car) = Cars += car
  ...
}

val composedInserts = (for {
    _ <- new UserRepository().insert(user)
    _ <- new CarRepository().insert(car)
} yield ()).result

db.run(composedInserts.transactionally)

Edit: clarified message

like image 118
Rikard Avatar answered Oct 13 '22 18:10

Rikard