Go进阶 - Xorm以及Gorm使用
原理咱就略过我知道很重要,奔着去实战学习
XORM
xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。xorm的目标并不是让你完全不去学习SQL,我们认为SQL并不会为ORM所替代,但是ORM将可以解决绝大部分的简单SQL需求。xorm支持两种风格的混用。
特性
- 支持Struct和数据库表之间的灵活映射,并支持自动同步
- 事务支持
- 同时支持原始SQL语句和ORM操作的混合执行
- 使用连写来简化调用
- 支持使用Id, In, Where, Limit, Join, Having, Table, SQL, Cols等函数和结构体等方式作为条件
- 支持级联加载Struct
- Schema支持(仅Postgres)
- 支持缓存
- 支持根据数据库自动生成xorm的结构体
- 支持记录版本(即乐观锁)
- 内置SQL Builder支持
- 通过EngineGroup支持读写分离和负载均衡
参考资料以及学习手册 常用~
安装
go get xorm.io/xorm
数据库连接
创建一个连接到 MySQL 数据库的引擎,首先定义一些变量来存储数据库连接所需的信息。
xorm.NewEngine("mysql", dataSourceName) 用于创建一个 xorm 引擎,该引擎将使用 MySQL 驱动连接到数据库
var (
username string = "root"
password string = "root1234"
ipAddress string = "127.0.0.1"
port int = 3306
dbName string = "go_test"
charset string = "utf8mb4"
)
dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s", username, password, ipAddress, port, dbName, charset)
// xorm.NewEngine()
engine, err := xorm.NewEngine("mysql", dataSourceName)
if err != nil {
fmt.Println("数据库连接失败")
}
Exec 执行一个SQL语句
affected, err := engine.Exec("update user set age = ? where name = ?", age, name)
当然也可以不用传参数 直接写在sql代码中
affected 是一个整数,表示受影响的行数,即更新操作影响的数据库记录数。
表操作
定义结构体,这里以User为例,后面的字段自行参考文档~
engine.Sync(new(User)) 用于将结构体 User 的定义与数据库表进行同步。这意味着它将根据结构体的定义自动创建或更新对应的数据库表结构,以确保它与结构体的定义保持一致。
type User struct {
Id int64
Name string
Age int
Passwd string `xorm:"varchar(200)"`
Created time.Time `xorm:"created"`
Updated time.Time `xorm:"updated"`
}
err = engine.Sync(new(User))
if err != nil {
fmt.Println("表结构同步失败")
}
数据操作
增
使用 engine.Insert 方法将结构体实例 user 插入到数据库中。&user 使用指针传递结构体实例的地址,以便 engine.Insert 方法可以修改结构体的字段值。n 是插入操作受影响的行数,用于判断插入是否成功。
user := User{Id: 1, Name: "huai", Age: 18, Passwd: "root"}
n, _ := engine.Insert(&user)
if n >= 1 {
fmt.Println("数据插入成功")
}
user1 := User{Id: 2, Name: "huai", Age: 18, Passwd: "root"}
user2 := User{Id: 3, Name: "huai", Age: 18, Passwd: "root"}
n, _ := engine.Insert(&user1, &user2)
if n >= 1 {
fmt.Println("success")
}
insert还可以插入users[]等...... 查阅API文档
删、改
改、删哪一个数据就写哪个
user = User{Name: "huai"}
n, _ = engine.ID(2).Delete(&user)
user = User{Name: "XJ"}
n, _ = engine.ID(1).Update(&user)
其他用法可查阅API文档
查
- Query
Get查询单条记录- Find查询多条记录
- Count 获取记录条数
- Iterater Rows根据条件遍历数据
res1, err := engine.Query("select * from user") //切片信息
res2, err := engine.QueryString("select * from user")
res3, err := engine.QueryInterface("select * from user")
// Get
user := User{Name: "huai"}
// ?号查询避免SQL注入
engine.Where("name=?", user.Name).Desc("id").Get(&user)
fmt.Println(user)
var name string
var passwd string
engine.Table(&user).Where("id=5").Cols("name", "passwd").Get(&name, &passwd)
fmt.Println(name, passwd)
// Find
var users []User
engine.Where("passwd=?", "root").And("age=?", 18).Limit(3, 0).Find(&users)
fmt.Println(users)
// Count 查询多少条数据
user := User{passwd: "root"}
cnt, err := engine.Count(&user)
fmt.Println(cnt)
err := engine.Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
user := bean.(*User)
return nil
})
// SELECT * FROM user
err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
user := bean.(*User)
return nil
})
// SELECT * FROM user Limit 0, 100
// SELECT * FROM user Limit 101, 100
// Rows 的用法类似 sql.Rows
rows, err := engine.Rows(&User{Name:name})
// SELECT * FROM user
defer rows.Close()
bean := new(Struct)
for rows.Next() {
err = rows.Scan(bean)
}
事务
GORM
特性
- 全功能 ORM
- 关联 (Has One,Has Many,Belongs To,Many To Many,多态,单表继承)
- Create,Save,Update,Delete,Find 中钩子方法
- 支持
Preload、Joins的预加载 - 事务,嵌套事务,Save Point,Rollback To Saved Point
- Context、预编译模式、DryRun 模式
- 批量插入,FindInBatches,Find/Create with Map,使用 SQL 表达式、Context Valuer 进行 CRUD
- SQL 构建器,Upsert,数据库锁,Optimizer/Index/Comment Hint,命名参数,子查询
- 复合主键,索引,约束
- Auto Migration
- 自定义 Logger
- 灵活的可扩展插件 API:Database Resolver(多数据库,读写分离)、Prometheus…
- 每个特性都经过了测试的重重考验
- 开发者友好
常用资料
安装
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite // sqline安装
go get -u gorm.io/driver/mysql // mysql安装
基本使用
定义gorm model
type Product struct{
ID uint `gorm:"primarykey"`
Code string `gorm:"colimn:code"`
Price uint `gorm:"default:0"`
}
为model定义表名
func (p Product) TableName() string{
return `product`
}
func main(){
// 连接数据库
db, err := gorm.Open(mysql.Open(dsn, &gorm.Config{}))
if err != nil{
panic("failed to connect database")
}
// 创建数据
db.Create($Product{Code:"D42", Price:100})
// 查询数据
var product Product
db.First(&product, 1) // 查询id = 1
db.First(&product, "code = ?", 200)
// 更新数据
// 将product的price更改为200
db.Model(&product).Update("Price", 200)
// 更改多个字段
db.Model(&product).Update(Product{Price:200, Code:"F42"})
db.Model(&product).Updata(map[string]interface{}{"Price":200, "Code":"F42"})
// 删除数据
db.Delete(&product, 1)
//
}
查询数据
// First 查询第一条数据 (主键升序)查询不到返回ErrRecordNotFound
// Find 查询一组数据 查询不到返回空数组 不会返回错误
users := make([]*User, 0)
res := db.Where("age > ?", 10).Find(&users)
res.RowsAffected //找到的记录数
res.Error //
删除数据
// 物理删除
db.Delete
// 软删除
// 添加表字段 Deleteed gorm.DeleteAt 即可实现软删除
// 使用Unscoped查询被软删的数据
事务
Gorm提供了Begin、Commit、Rollback方法用于使用事务
tx := db.Begin() // 开启事务
if err = tx.Create(&User{Name:"name"}).Error; err != nil{
tx.Rollback() // 回滚事务
return
}
if err = tx.Create(&User{Name:"name1"}).Error; err != nil{
tx.Rollback()
return
}
//提交事务
tx.Commit()
Gorm提供了Transaction方法用于自动提交事务,避免用户漏泄Commit Rollback
if err = db.Transaction(func(tx *gorm.DB) error{
if err = tx.Create(&User{Name:"name"}).Error; err != nil{
return err
}
if err = tx.Create(&User{Name:"name"}).Error; err != nil{
tx.Rollback() // ??????
return err
}
return nil
}); err != nil{
return
}
Hook
Hook是在创建、查询、删除、更新等操作之前、之后自动调用的函数
如果任何Hook返回错误,GORM将停止后续的操作并回滚事务
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
if u.Age < 0{
return errors.New("can't save invalid data")
}
return
}
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
return tx.Create(&Email{ID:u.ID, Email:u.Name + "@qq.com", }).Error
}
性能提高
&gorm.Config{
// 禁用默认事务
// 对于写操作(创建、更新、删除),为了确保数据的完整性,GORM 会将它们封装在一个事务里。但这会降低性能,你可以在初始化时禁用这种方式
SkipDefaultTransaction: true,
// 缓存预编译语句
// 执行任何 SQL 时都创建并缓存预编译语句,可以提高后续的调用速度
PrepareStmt: true,
}

浙公网安备 33010602011771号