-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
94 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,84 @@ | ||
play-dbx [中文说明](README_zh.md) | ||
================================= | ||
A transaction management library that makes it simple while using PlayFramework's DBApi | ||
A transaction management library that makes it simple while using transactional resources, e.g. play-jdbc, anorm, etc, in PlayFramework. | ||
The original source code is migrated from **Spring Framekwork** 's `spring-tx`, `spring-jdbc` and `spring-context` modules, and remove any unnessery classes. It's aim is to provide a clean and no external dependencies transaction management framework for `Play Framework`. It supports `Play DBApi` a.k. `play-jdbc` out of box, you can refer the instructions bellow. | ||
The core component/interface of `play-dbx` is `Transactional`, `TransactionSettings` and `TransactionManagerLookup`, and the default implementation of `Transactional` is `SimpleDBApiTransactional` and `SimpleDBApiTransactionManagerLookup` for `TransactionManagerLookup`, pelease refere the source code for more details. | ||
|
||
## Add dependency to you project(build.sbt) | ||
```sbt | ||
libraryDependencies += "com.lingcreative" %% "play-dbx" % "1.0.1" | ||
``` | ||
## Steps(take `Anorm` for example) | ||
|
||
#### Config bindings for Dependency Injection | ||
```scala | ||
// app/Module.scala | ||
|
||
class Module extends AbstractModule { | ||
override def configure(): Unit = { | ||
//Use the out-of-boxed TransactionManagerLookup for DBApi, which create a individual DataSourceTransactionManager | ||
//for each DataSource looked up from `DBApi.database(name).datasource` | ||
bind(classOf[TransactionManagerLookup]).to(classOf[SimpleDBApiTransactionManagerLookup]) | ||
|
||
//Use the out-of-boxed Transactional for DBApi, which gets a connection from `DBApi.database(name).datasource` | ||
//and bind it to the current transaction context | ||
val transactionalKey = new TypeLiteral[Transactional[Connection]](){} | ||
bind(transactionalKey).to(classOf[SimpleDBApiTransactional]) | ||
|
||
//Make the db named `default1` configured in application.conf as the default datasource, and set JDBC isolation level | ||
//to repeatable read | ||
//Refer [[dbx.transaction.Transactional]]、[[dbx.transaction.Transactional.TransactionSettings]] for details. | ||
val settings = TransactionSettings(isolation = Isolation.REPEATABLE_READ, resource = "default1") | ||
bind(classOf[TransactionSettings]).toInstance(settings) | ||
} | ||
} | ||
|
||
``` | ||
|
||
#### Make code transactional(modified from [play-anorm](https://github.com/playframework/play-scala-anorm-example)) | ||
```scala | ||
import java.sql.Connection | ||
import javax.inject._ | ||
|
||
import anorm.SqlParser._ | ||
import anorm._ | ||
|
||
// The main interface to use | ||
import dbx.api.Transactional | ||
|
||
case class Company(id: Option[Long] = None, name: String) | ||
|
||
@Singleton | ||
class CompanyService @Inject() (transactional: Transactional[Connection]/*Inject the SimpleDBApiTransactional for JDBC operations*/) { | ||
|
||
/** | ||
* Parse a Company from a ResultSet | ||
*/ | ||
val simple = { | ||
get[Option[Long]]("company.id") ~ | ||
get[String]("company.name") map { | ||
case id~name => Company(id, name) | ||
} | ||
} | ||
|
||
/** | ||
* Get connection from `default1` db configured in application.conf, and rollback if any `Exception` thrown | ||
*/ | ||
def options: Seq[(String,String)] = transactional() { implicit connection => | ||
SQL("select * from company order by name").as(simple *). | ||
foldLeft[Seq[(String, String)]](Nil) { (cs, c) => | ||
c.id.fold(cs) { id => cs :+ (id.toString -> c.name) } | ||
} | ||
} | ||
|
||
/** | ||
* Allow update and delete sql to execute, pick connection from `default`, and rollback if any `CompanyExistException`, | ||
* it equals to `@Transactional(readOnly=true, transactionManager="default", rollbackFor={CompanyExistException.class})` in SpringFramework. | ||
*/ | ||
def save(company: Company): Unit = transactional(readOnly = false, resource = "default", rollbackFor = Array(classOf[CompanyExistException])) { implicit connection => | ||
// execute sql update statements here ... | ||
} | ||
|
||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters