golang gorm事务踩坑记
1 源码
package gorm
import (
"fmt"
"regexp"
"strings"
"gorm.io/gorm/clause"
"gorm.io/gorm/utils"
)
// Model specify the model you would like to run db operations
// // update all users's name to `hello`
// db.Model(&User{}).Update("name", "hello")
// // if user's primary key is non-blank, will use it as condition, then will only update the user's name to `hello`
// db.Model(&user).Update("name", "hello")
func (db *DB) Model(value interface{}) (tx *DB) {
tx = db.getInstance()
tx.Statement.Model = value
return
}
// Table specify the table you would like to run db operations
func (db *DB) Table(name string, args ...interface{}) (tx *DB) {
tx = db.getInstance()
if strings.Contains(name, " ") || strings.Contains(name, "`") || len(args) > 0 {
tx.Statement.TableExpr = &clause.Expr{SQL: name, Vars: args}
if results := tableRegexp.FindStringSubmatch(name); len(results) == 2 {
tx.Statement.Table = results[1]
return
}
} else if tables := strings.Split(name, "."); len(tables) == 2 {
tx.Statement.TableExpr = &clause.Expr{SQL: tx.Statement.Quote(name)}
tx.Statement.Table = tables[1]
return
}
tx.Statement.Table = name
return
}
2 关键方法
2.1 Model----> Model specify the model you would like to run db operations
2.2 Table----> Table specify the table you would like to run db operations
3 坑
在Tx中 开启事务Begin 直到commit ,如果中间涉及两个及以上不同的表操作,则在切换表是需要同时执行model 和 table 方法。否则,将会遇到表名和字段不配的异常,如果恰巧误匹配上,那简直是悲剧。
4 原因分析