Improving GORM integration with Revel and Adding Transaction Support

In an earlier post, I talked about Integrating GORM with Revel app . Moving further with querying the data I used a new connection to query.

As I moved on, I needed transactions support. I looked at the booking sample app with Revel documentation. In particular gorp.go

Looking at that, I had to update my code base to add transactions support. I added Begin(), Commit() and Rollback() methods as below

func (c *GormController) Begin() revel.Result {
	txn := db.Begin()

	if txn.Error != nil {
		panic(txn.Error)
	}
	c.Txn = txn
	return nil
}

// This method clears the c.Txn after each transaction
func (c *GormController) Commit() revel.Result {
	if c.Txn == nil {
		return nil
	}
	c.Txn.Commit()
	if err := c.Txn.Error; err != nil && err != sql.ErrTxDone {
		panic(err)
	}
	c.Txn = nil
	return nil
}

// This method clears the c.Txn after each transaction, too
func (c *GormController) Rollback() revel.Result {
	if c.Txn == nil {
		return nil
	}
	c.Txn.Rollback()
	if err := c.Txn.Error; err != nil && err != sql.ErrTxDone {
		panic(err)
	}
	c.Txn = nil
	return nil
}

Now to use these methods, while updating and querying database, we need to do

user := &models.User{}
	c.Begin()
	defer func() {
             //todo: Check transaction is not committed already
		c.Rollback()
	}()
	c.Txn.Save(user)
	c.Commit()

Here, we begin a transaction, we call Rollback in defer to ensure that if there is any problem or error we rollback the entire transaction.

We save the user in transaction and then commit() the transaction.

In the above code, it will now call the rollback() method after commit(), so you would see a
“(sql: Transaction has already been committed or rolled back)” Message.

Once, we follow this pattern, we don’t need to do db.New() anymore.

Let me know, what you think!

~~ Whizdumb ~~
Email : sachin.xpert@gmail.com