golang gorm事务踩坑记

2,461 阅读1分钟

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 原因分析