这是我参与「第五届青训营 」伴学笔记创作活动的第6天。
Database/sql 及 GORM 相关解读
db,err:=sql.Open(,)
初始化DB连接
rows,err:=db.Query(,)
执行一条SQL,通过rows获取返回值
defer rows.Close()
最后释放链接
err:=rows.Scan(,)
数据读取
只需要不同的接口来支持不同的数据
池化技术来优化性能
连接池设计原理
连接池配置
func(db *DB)SetConnMaxIdleTime(d time.Duration)
func(db *DB)SetConnMaxLifeTime(d time.Duration)
func(db *DB)SetMaxIdleConns(n int)
func(db *DB)SetMaxOpenConns(n int)
连接池状态
func(db *DB)Stats() DBStats
Driver连接接口
type Driver interface{
Open(name string)(Conn,error)
}
注册全局driver
func Register(name string,driver driver.Driver){
driversMu.Lock()
defer driversMu.Unlock
if driver==nil{
panic("sql:Register driver is nil")
}
if _,dup:=drivers[name];dup{
panic("sql:Register called twice for driver"+name)
}
drivers[name]=driver
}
Connector连接接口
type Connector interface{
Connect(context.Context)(Conn,err)
Driver() Driver
}
Connector使用例子
connector,err:=mysql.NewConnector(&mysql.Config{User:"gorm",Passwd:"gorm",Net:"tcp",Addr:"127.0.0.1:3306",DBName:"gorm",ParseTime:true,})
db:=sql.OpenDB(connector)
连接方式:tcp连接,pre-statement连接
数据处理方式:Exec/ExecContext->Result,Query/QueryContext->Rows(Columns),QueryRow/QueryRowContext->Row
type driver.Rows interface{
Columns() []string
Next(dest []Value)error
HashNextResultSet() bool
NextResultSet() error
}
type Rows struct{
dc *driverConn
lastcols []driver.Value
}
GORM是设计简洁、功能强大、自由扩展的全功能ORM
GORM设计原则:API精简、测试优先、最小惊讶、灵活扩展、无依赖
CRUD操作
db.AutoMigrate(&Product{})
db.Migrator().CreateTable(&Product{})
操作数据库
user:=User{Name:"Ben",Age:"18",Birthday:time.Now()}
result:=db.Create(&user)
创建
user.ID
返回主键中最后传入的ID
result.Error
返回error
result.RowAffected
返回影响行数
var user=[]User{{Name:"1"},{Name:"2"},{Name:"3"}}
db.Create(&users)
db.CreateInBatches(user,100)
批量创建
db.First(&product,1)
查询id为1的product
db.First(&product,"code=?","L12")
查询code为L12的product
db.Model(&product).Unpate("Price",2000)
更新单个字段
db.Model(&product).Updates(Product{"Price":2000,Coed:"L13"})
更新多个字段
db.Model(&Product{}).Where("price<?",2000).Updates(map[string]interface{}{"Price":2000})
批量更新
模型定义
type User struct{
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreateAt time.Time
UpdatedAt time.Time
DeletedAt gorm.Delete gorm:"index"
}
yueding表名为结构名的复数
ID一般为自增主键
时间默认为保存文件的时间
langAssociation:=db.Model(&user).Association("Languages")
关联模式
langAssociation.Find(&languages)
查询关联
db.Prelood("Orders.OrderItems.Product").Prelood(clause.Association).Find(&users)
多级预加载,并将预加载全部一级关联
级联删除
db.Select("Account").Delete(&user)
删除user的account和user
db.Select("Orders","CreditCards").Delete(&user)
删除user和user的Orders、CreditCards记录
GORM设计原理
SQL语句组成:Finish Method和GORM Clauses。
GORM API方法添加Clauses至GORM Statement。
使用GORM的原因:可以自定义Clause Builder,方便扩展Clause,自由选择Clauses。
GORM会先发送请求获得SQL的版本,根据版本来初始化参数,在利用参数来生成SQL代码。
GORM可以扩展子句,在编译过程中会自动扩展。
扩展SELECT Clauses
db.Clauses(hints.New("idx1")).Find(&User{})
扩展FROM Clauses
db.Clauses(hints.UseIndex("idx_user_name")).Find(&User{})
db.Clauses(hints.ForceIndex("idx_user_name","idx_user_id").ForJoin()).Find(&User{})
自由扩展Clauses
db.Clauses(hints.CommentBefore("insert","node2)).Create(&user)
db.Clauses(hints.CommentAfter("where","hint")).Find(&User{},"id=?",1)
插件工作方式:Finish Method->插件系统(决定Statement类型->执行Callbacks->生成SQL并执行)
Callbacks模式:Create、Query、Update、Delete、Row、Raw
Create:第一次用开启事务,第二次开启方法,都是进行一些预定义
GORM通过SQL操作ConnPool,数据库读写DB通过DML Statement来接受ConnPool中的信息,最后ConnPool处理事务。
ConnPool不能直接连接数据库
应用程序通过GORM利用ConnPool插件通过连接池连接数据库
执行前预编译SQL,调用预编译的SQL,关闭预编译的SQL。
Dialector就是可以让GORM实现查询MySQL等功能的
Dialector可以定制SQL生成,定制GORM插件,定制ConnPool,定制企业特性逻辑。