Changes behavior between sqlx.DB
and sqlx.Tx
in runtime.
go get -u github.com/andresmijares/sqlxtx
// db.go
// Will manage each operation independently
func init() {
datasourceName := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",
username,
password,
host,
schema)
var err error
Client, err = sqlx.Open("mysql", datasourceName)
if err != nil {
panic(err)
}
WithTx = &sqlxtx.EnableSqlxTx{
Client: Client,
Config: sqlxtx.Config{
Verbose: true,
},
}
}
// domain.go
type User struct {
Client *sqlx.DB
}
func (u *User) Create(username, password string) error {
_, err := u.Client.NamedExec("INSERT INTO users (first_name, last_name) VALUES (:first_name, :last_name);",
map[string]interface{}{
"first_name": "Jhon",
"last_name": "Doe",
})
if err != nil {
return err
}
return nil
}
type Events struct {
Client *sqlx.DB
}
func (u *Events) Create(name string) error {
_, err := e.Client.NamedExec(`INSERT INTO events(name) VALUE (:name);`,
map[string]interface{}{
"name": name,
})
if err != nil {
return err
}
return nil
}
// service.go
UserDao := &User{
Client: Client,
}
EventsDao := &Events{
Client: Client,
}
func CreateUser () {
if err := UserDao.Create(); err != nil {
return err
}
if err := EventsDao.Create("userCreated"); err != nil {
return err
}
return nil
}
// Will run a transaction, not need to modify the underline implementation
func CreateUserWithTx () {
if err := db.WithTx.Exec(func() error {
if err := UserDao.Create(); err != nil {
return err
}
if err := EventsDao.Create("userCreated"); err != nil {
return err
}
return nil
}); err != nil {
return err
}
return nil
}
Sample how to test this can be found in the sample folder.
I've mocked only the most commons methods I use, for a more detailed list, please check sqltxmocks
Nested transactions are not supported, yet.
Transactions should be implementation details, it should not force developers to re-write code to support between Tx
and DB
. I couldn't find a solid way to decorate
operations in my services, so I created this one.
I found a lot of motivation in this articles.
- sqlx
- detect-and-commit-rollback
- db-transaction-in-golang
- golang transactions api design
- A clean way to implement database transaction in golang
- Go Microservice with clean architecture: transaction support
- Isolation levels
I only added the methods I use, please, feel free to submit PR's to support more methods.
MIT