当前位置:网站首页>Gorm transaction experience
Gorm transaction experience
2022-06-28 05:12:00 【. fried eggs with tomatoes】
brief introduction
gorm Transaction Chinese document
surface
CREATE TABLE `accounts` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`money` decimal(30,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

No transaction
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
type Account struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(10);not null"`
Money float64 `gorm:"type:decimal(30,2);not null"`
}
func main() {
// Connect to the corresponding database
dsn := fmt.Sprintf("%s:%[email protected](%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "root", "127.0.0.1", 3306, "test")
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer( The target of log output , Prefix and what the log contains —— translator's note )
logger.Config{
SlowThreshold: time.Second, // slow SQL threshold
LogLevel: logger.Info, // The level of logging
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound( Record not found ) error
Colorful: true, // Use color printing
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
a := 1 - 1
// Simulate Zhang San to Li sizhuan 100
account := Account{
ID: 1, Name: " Zhang San ", Money: 900}
account1 := Account{
ID: 2, Name: " Li Si ", Money: 1100}
db.Save(&account)
if true {
// Manually make an error
_ = 1 / a
}
db.Save(&account1)
}

An exception was manually created in the code , Under normal circumstances, the transfer should fail , The balance of both men is still 1000, But since no transaction is used , Zhang San has already deducted money , But Li Si didn't receive the money , This is absolutely unacceptable in the real scene .
Business
package main
import (
"errors"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
type Account struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(10);not null"`
Money float64 `gorm:"type:decimal(30,2);not null"`
}
func main() {
// Connect to the corresponding database
dsn := fmt.Sprintf("%s:%[email protected](%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "root", "127.0.0.1", 3306, "test")
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer( The target of log output , Prefix and what the log contains —— translator's note )
logger.Config{
SlowThreshold: time.Second, // slow SQL threshold
LogLevel: logger.Info, // The level of logging
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound( Record not found ) error
Colorful: true, // Use color printing
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
db.Transaction(func(tx *gorm.DB) error {
// Simulate Zhang San to Li sizhuan 100
account := Account{
ID: 1, Name: " Zhang San ", Money: 800}
account1 := Account{
ID: 2, Name: " Li Si ", Money: 1100}
tx.Save(&account)
if true {
return errors.New(" Manually make an error ")
}
tx.Save(&account1)
return nil
})
}

It is normal to use transactions , Errors will roll back , Returning any error rolls back the transaction
Nested transactions
package main
import (
"errors"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
type Account struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(10);not null"`
Money float64 `gorm:"type:decimal(30,2);not null"`
}
func main() {
// Connect to the corresponding database
dsn := fmt.Sprintf("%s:%[email protected](%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "root", "127.0.0.1", 3306, "test")
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer( The target of log output , Prefix and what the log contains —— translator's note )
logger.Config{
SlowThreshold: time.Second, // slow SQL threshold
LogLevel: logger.Info, // The level of logging
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound( Record not found ) error
Colorful: true, // Use color printing
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
db.Transaction(func(tx *gorm.DB) error {
// Simulate Zhang San to Li sizhuan 100
account := Account{
ID: 1, Name: " Zhang San ", Money: 800}
account1 := Account{
ID: 2, Name: " Li Si ", Money: 1100}
tx.Save(&account)
tx.Transaction(func(tx *gorm.DB) error {
// In nested transactions, imitate Wang Wu to Zhao liuzhuan 100
account2 := Account{
ID: 3, Name: " Wang Wu ", Money: 900}
account3 := Account{
ID: 4, Name: " Zhao Liu ", Money: 1100}
tx.Save(account2)
if true {
return errors.New(" Manually make an error ")
}
tx.Save(account3)
return nil
})
tx.Save(&account1)
return nil
})
}

This error occurs in nested transactions , Zhang San's transfer to Li Si was normally completed , But Wang Wu's transfer to Zhao Liu was rolled back
Manual transactions
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
type Account struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(10);not null"`
Money float64 `gorm:"type:decimal(30,2);not null"`
}
func main() {
// Connect to the corresponding database
dsn := fmt.Sprintf("%s:%[email protected](%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "root", "127.0.0.1", 3306, "test")
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer( The target of log output , Prefix and what the log contains —— translator's note )
logger.Config{
SlowThreshold: time.Second, // slow SQL threshold
LogLevel: logger.Info, // The level of logging
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound( Record not found ) error
Colorful: true, // Use color printing
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
// Simulate Zhang San to Li sizhuan 100
// Open transaction
tx := db.Begin()
account := Account{
ID: 1, Name: " Zhang San ", Money: 700}
account1 := Account{
ID: 2, Name: " Li Si ", Money: 1200}
if result := tx.Save(&account); result.Error != nil {
// Error rollback
tx.Rollback()
}
if result := tx.Save(&account1); result.Error != nil {
// Error rollback
tx.Rollback()
}
// Commit transaction
tx.Commit()
}

There were no errors in the process , Transaction transfer submitted successfully . Manual transaction pair error Judge , If error Not for nil Just use it tx.Rollback() Just roll back the transaction .
SavePoint、RollbackTo
GORM Provides SavePoint、Rollbackto Method , To provide savepoint and rollback to savepoint
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
type Account struct {
ID uint `gorm:"primarykey"`
Name string `gorm:"type:varchar(10);not null"`
Money float64 `gorm:"type:decimal(30,2);not null"`
}
func main() {
// Connect to the corresponding database
dsn := fmt.Sprintf("%s:%[email protected](%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
"root", "root", "127.0.0.1", 3306, "test")
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer( The target of log output , Prefix and what the log contains —— translator's note )
logger.Config{
SlowThreshold: time.Second, // slow SQL threshold
LogLevel: logger.Info, // The level of logging
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound( Record not found ) error
Colorful: true, // Use color printing
},
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
if err != nil {
panic(err)
}
// Simulate Zhang San to Li sizhuan 100
// Imitate Wang Wu to Zhao liuzhuan 100
account := Account{
ID: 1, Name: " Zhang San ", Money: 600}
account1 := Account{
ID: 2, Name: " Li Si ", Money: 1300}
account2 := Account{
ID: 3, Name: " Wang Wu ", Money: 900}
account3 := Account{
ID: 4, Name: " Zhao Liu ", Money: 1100}
tx := db.Begin()
tx.Save(&account)
tx.Save(&account1)
tx.SavePoint("test")
tx.Save(&account2)
tx.Save(&account3)
if true {
// Rollback here , Only transfer money from Zhang San to Li Si
tx.RollbackTo("test")
}
tx.Commit()
}

Use tx.RollbackTo(“test”) Roll back to tx.SavePoint(“test”) Before , Only transfer money from Zhang San to Li Si ; The transfer from Wang Wu to Zhao Liu has not been completed
Be careful



In the official documents , The author adheres to the principle of saying important things three times , Once a transaction starts, you should use tx Processing data , This needs special attention , If you use the pre transaction db Deal with affairs , If an error occurs, it will not be rolled back
边栏推荐
- Voltage mode and current mode control of switching power supply
- [skywalking] learn distributed link tracking skywalking at one go
- 为什么大厂不让使用undefined
- RxSwift --(1)创建一个项目
- 创新之源 理解通透 二
- Latest Windows version 5.0.14 of redis
- PCR/qPCR研究:Lumiprobe丨dsGreen 用于实时 PCR
- C语言中函数是什么?编程中的函数与数学中的函数区别?理解编程语言中的函数
- 公司为什么选择云数据库?它的魅力到底是什么!
- The heading angle of sliceplane is the same as that of math Corresponding transformation relation of atan2 (y, x)
猜你喜欢

开关电源电压型与电流型控制

The number of small stores in Suning has dropped sharply by 428 in one year. Zhangkangyang, the son of Zhang Jindong, is the actual controller

Latest Windows version 5.0.14 of redis

JS text box loses focus to modify width text and symbols

How high is the gold content of grade II cost engineer certificate? Just look at this

Redis 的 最新windows 版本 5.0.14

Feign implements path escape through custom annotations

Learn Taiji Maker - mqtt Chapter 2 (IV) esp8266 reserved message application

Leetcode 88: merge two ordered arrays

Severe tire damage: the first rock band in the world to broadcast live on the Internet
随机推荐
RxSwift --(1)创建一个项目
Analysis of distributed transaction solution Seata golang
Severe tire damage: the first rock band in the world to broadcast live on the Internet
Excel将一行的内容进行复制时,列与列之间是用制表符“\t”进行分隔的
Latest Windows version 5.0.14 of redis
乔布斯在斯坦福大学的演讲稿——Follow your heart
Feign remote call fallback callback failed, no effect
2022年G3锅炉水处理复训题库模拟考试平台操作
Keil C51的Data Overlaying机制导致的函数重入问题
JS 文本框失去焦点修改全半角文字和符号
wordpress zibll子比主题6.4.1开心版 免授权
BioVendor sRAGE蛋白解决方案
【JVM系列】JVM调优
BioVendor sRAGE Elisa试剂盒化学性质和技术研究
Audio and video technology development weekly
Amino dye research: lumiprobe fam amine, 6-isomer
创新之源 理解通透 二
BioVendor sRAGE抗体解决方案
The number of small stores in Suning has dropped sharply by 428 in one year. Zhangkangyang, the son of Zhang Jindong, is the actual controller
Performance degradation during dpdk source code testing