前言
go中操作数据库一般使用gorm
框架进行,而较少用原生的datebase/sql
包。标准库的datebase/sql
包需要手写sql,对于简单的sql操作来说过于繁琐,因此平时开发更倾向于使用gorm
。而说到数据库操作,就离不开事务管理,gorm
支持事务管理,并且非常灵活、简单
介绍
开启事务
1 2 3 4
| tx := db.Begin() if tx.Error != nil { return tx.Error }
|
当发生错误时,回滚事务
1 2 3
| if err != nil { tx.Rollback() }
|
提交事务
1 2 3 4
| if err := tx.Commit().Error;err != nil { tx.Rollback() }
|
事务失效的情况
由于每次gorm操作数据库时,都会向连接池获取一个连接,这些连接不共享一个事务,因此在涉及多张表操作时,如果想由同一个事务控制,则需要使用由db.Begin()
开启事务时返回的tx
对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| func (s *TaskService) AddTeamTask(task models.Task) error { tx := s.teamTaskRepository.Db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }()
if err := s.taskRepository.Create(&task); err != nil { tx.Rollback() return err }
teamTask := models.TeamTask{ TaskId: task.Id, UserId: task.UserId, Status: 0, }
if err := s.teamTaskRepository.Create(&teamTask); err != nil { tx.Rollback() return err }
return tx.Commit().Error }
|
两张表插入数据时,都在使用自己的数据库连接,并没有用到tx
,不共享同一个事务,此时即使tx.Rollback()
也是无效的回滚。
直接操作
更加简单快速、适合快速开发
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| func (s *TaskService) AddTeamTask(task models.Task) error { tx := s.teamTaskRepository.Db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }()
if err := tx.Create(&task); err != nil { tx.Rollback() return err }
teamTask := models.TeamTask{ TaskId: task.Id, UserId: task.UserId, Status: 0, }
if err := tx.Create(&teamTask); err != nil { tx.Rollback() return err }
return tx.Commit().Error }
|
数据库层支持传入操作指针
更加灵活,而且保留了数据库操作的封装性。同时也保持了代码的可读性,可根据调用的对象和函数快速判断在向哪张数据库表进行什么操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| func (s *TaskService) AddTeamTask(task models.Task) error { tx := s.teamTaskRepository.Db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }()
if err := s.taskRepository.Create(&task,tx); err != nil { tx.Rollback() return err }
teamTask := models.TeamTask{ TaskId: task.Id, UserId: task.UserId, Status: 0, }
if err := s.teamTaskRepository.Create(&teamTask,tx); err != nil { tx.Rollback() return err }
return tx.Commit().Error }
|
在不需要事务管理时,只需要传入nil
即可。