Skip to content

事务

基本

go
// 1. 开启事务
tx := db.Begin()
if tx.Error != nil {
    fmt.Println("开启事务失败")
    return
}

// 2. 执行操作1
if err := tx.Create(&User{Name: "李四"}).Error; err != nil {
    tx.Rollback() // 失败回滚
    fmt.Println("创建用户失败")
    return
}

// 3. 执行操作2
if err := tx.Create(&Log{Content: "手动事务测试"}).Error; err != nil {
    tx.Rollback()
    fmt.Println("创建日志失败")
    return
}

// 4. 全部成功 → 提交事务
if err := tx.Commit().Error; err != nil {
    fmt.Println("提交失败")
}

v1

定义

go
type IUserRepo interface {
	WithTx(tx *gorm.DB) IUserRepo

	CreateUser(ctx context.Context, user *CreateUserInput) (*UserEntity, error)
}

实现

go

type UserRepo struct {
	db *gorm.DB
}

func NewUserRepo(db *gorm.DB) userdomain.IUserRepo {
	return &UserRepo{
		db: db,
	}
}

func (r *UserRepo) WithTx(tx *gorm.DB) userdomain.IUserRepo {
	return &UserRepo{
		db: tx,
	}
}

func (r *UserRepo) CreateUser(ctx context.Context, user *userdomain.CreateUserInput) (*userdomain.UserEntity, error) {
	model := &userdomain.UserModel{
		Account:  user.Account,
		Email:    user.Email,
		Phone:    user.Phone,
		Nickname: user.Nickname,
	}

	if err := r.db.WithContext(ctx).Create(model).Error; err != nil {
		return nil, err
	}

	return userdomain.Model2entity(model), nil
}

使用

go
s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {

		user := &userdomain.CreateUserInput{
			Account:  email,
			Email:    email,
			Phone:    fmt.Sprintf("unbound:%s", email),
			Nickname: nick,
		}

		userRepo := s.userRepo.WithTx(tx)
		userEntity, err := userRepo.CreateUser(ctx, user)

		if err != nil {
			return err
		}

		authRepo := s.repo.WithTx(tx)
		err = authRepo.CreateAuth(ctx, &authdomian.UserAuthEntity{
			ID:       userEntity.ID,
			Password: string(hash),
		})

		if err != nil {
			return err
		}

		return nil
	})