Wrap DB Transaction with Abstraction Golang

Aris Haryanto
2 min readMar 10, 2023

--

I want to show you how to write DB transaction with abstraction
in Flat Architecture on my previous article

You can read it first here Best Way To Structuring Golang Code
before continue

Okayy . . .

Now for last code I created, I’ve little modification to support abstract transaction
so for the first, we move adapter.go to api directory, because we need to create sub abstraction from parent interface

the code look like this

api/adapter.go

if you realize from previous code, I add 2 function CreateSomething this function will insert data to DB, and WrapTx
this will wrap entire parent interface in function argument

this function argument will handle abstract function from SqlDB struct in adapters
so when you call WrapTx you can call abstract function SqlDB inside function argument

Next I add some function in adapters/sql.go

adapters/sql.go

I Create SqlDBTx struct for handled new sub abstraction from function argument and TxConn to handled Tx connection inside WrapTx

this is the code of WrapTx function

adapters/sql.go

As you can see, first we call sqldb.sqlConn.Begin() as tx connection
and we apply this tx to function TxConn this will return interface from api/adapter.go
so we put this return to fn which is function argument

and what should we do in here is only grab the error, so when we got errors
from this fn(q) , this WrapTx function will do rollback transaction

otherwise they will return Commit().Error this will return error when you got error or nil when success

Next I was updated code hello_service.go to call function WrapTx from bussiness logic

services/hello_service.go

So when we call WrapTx the function will look like this
inside of function argument you can call the abstraction from current connection (DB you use)

also you can call other function not only from that function argument.
As you can see, I call failTx function from outside function argument, so this will simulate your transaction to fail

you just need to return error when you want to rollback this transaction

it’s very simple right !

Benefit

So what is benefit for using this abstraction in Flat Architecture ?
Your code will . . .

  • easy to maintain
    i.e when you want to change to other DB with different transaction function
    you don’t need to change the bussiness logic,
    you just need to add new DB in adapters and implement WrapTx and write the transaction code inside this function with requirement from DB it self
  • easy to read and simple
    As you can see, you don’t need to call rollback on every statement,
    just return error then they will rollback automaticly

you can check full code here https://github.com/Aris-haryanto/Best-Way-To-Structuring-Golang-Code/tree/abstract_transaction

--

--