model定义
type Roles []string
type Teacher struct {
gorm.Model
Name string `gorm:"size:256"`
Email string `gorm:"size:256"`
Salary float64 `gorm:"scale:2;precision:7"` // 指定小数部分宽度为2,列宽度为7. 列宽:【整数部分+小数部分的总长度】【不含小数点】
Age uint8 `gorm:"check:age>30"`
Birthday int64 `gorm:"serializer:unixtime;type:time"` // 反序列化方式 unixtime, 类型为time
Roles Roles `gorm:"serializer:json"`
JobInfo Job `gorm:"embedded;embeddedPrefix:job_"` // 嵌套字段, 嵌入字段的列名前缀job_
JobInfo2 Job `gorm:"type:bytes;serializer:gob"` // 字节流类型,gob反序列化,go自己的序列化方法,跨语言项目的时候,不建议用
}
type Job struct {
Title string
Location string
}
type Course struct {
gorm.Model
Name string `gorm:"size:256"`
Price float64 `gorm:"scale:2;precision:7"`
UserID uint `gorm:"type:int"`
}
gorm提供了自动事务的机制,不需要我们手动提交和回滚
func Transaction() {
t := Teacher{
Name: "yuan",
Age: 41,
Salary: 122345.123,
Email: "[email protected]",
}
c := Course{
Name: "golang",
Price: 12345.1234,
}
DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&t).Error; err != nil {
// 返回err 会自动回滚事务
return err
}
c.UserID = t.ID
if err := tx.Create(&c).Error; err != nil {
return err
}
// 返回nil 则提交事务
return nil
})
}
gorm事务可以嵌套,大事务里嵌套小事务,只有大事务成功提交,必须大事务提交成功,内部嵌套的事务才能提交成功。如果失败了,可以回滚嵌套的事务。
注意:嵌套事务不应在gorm中大量使用,因为其不支持预编译。
func NestTransaction() {
t := Teacher{
Name: "yuan",
Age: 41,
Salary: 122345.123,
Email: "[email protected]",
}
t1 := Teacher{
Name: "yuan2",
Age: 40,
Salary: 12345.123,
Email: "[email protected]",,
}
t2 := Teacher{
Name: "yuan3",
Age: 50,
Salary: 12345.123,
Email: "[email protected]",,
}
DB.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&t).Error; err != nil {
return err
}
tx.Transaction(func(tx1 *gorm.DB) error {
if err := tx1.Create(&t1).Error; err != nil {
return err
}
return nil
})
tx.Transaction(func(tx1 *gorm.DB) error {
if err := tx1.Create(&t2).Error; err != nil {
return err
}
return nil
})
return nil
})
}
gorm也提供了begin, rollback等接口支持手动事务的操作
func ManualTransaction() {
t := Teacher{
Name: "yuan",
Age: 41,
Salary: 122345.123,
Email: "[email protected]",
}
c := Course{
Name: "golang",
Price: 12345.1234,
}
tx := DB.Begin()
defer func() {
if err := recover(); err != nil {
tx.Rollback()
}
}()
if tx.Error != nil {
log.Fatal(tx.Error)
return
}
if err := tx.Create(&t).Error; err != nil {
tx.Rollback()
return
}
c.UserID = t.ID
if err := tx.Create(&c).Error; err != nil {
tx.Rollback()
return
}
tx.Commit()
}
gorm也提供了savePoint的机制来支持事务的分段提交,回滚到某个特定的savePoint(RollbackTo)
func SavePointTransaction() {
t := Teacher{
Name: "yuan",
Age: 41,
Salary: 122345.123,
Email: "[email protected]",
}
c := Course{
Name: "golang",
Price: 12345.1234,
}
tx := DB.Begin()
defer func() {
if err := recover(); err != nil {
tx.Rollback()
}
}()
if tx.Error != nil {
log.Fatal(tx.Error)
return
}
if err := tx.Create(&t).Error; err != nil {
tx.Rollback()
return
}
// 创建savepoint
tx.SavePoint("teacher")
c.UserID = t.ID
if err := tx.Create(&c).Error; err != nil {
// 回滚到对应savepoint
tx.RollbackTo("teacher")
return
}
tx.Commit()
}