GORM相关解读|青训营笔记

136 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第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,定制企业特性逻辑。