文章来源:http://gf.johng.cn/494380node
gf框架的数据库ORM操做由gdb包提供支持,gdb包通过很是精心优雅的设计,提供了很是强大的配置管理、方法操做、链式操做、事务操做等功能。gdb包具体API说明文档详见:godoc 。本章节对gdb包的使用进行基本的介绍,包括:gdb包基本功能介绍,配置管理功能说明,常见用法及经常使用操做示例。mysql
使用方式:git
import "gitee.com/johng/gf/g/database/gdb"
gdb数据结构:github
type List []Map // 数据记录列表 type Map map[string]interface{} // 数据记录 type Config map[string]ConfigGroup // 数据库配置对象 type ConfigGroup []ConfigNode // 数据库分组配置 // 数据库配置项(一个分组配置对应多个配置项) type ConfigNode struct { Host string // 地址 Port string // 端口 User string // 帐号 Pass string // 密码 Name string // 数据库名称 Type string // 数据库类型:mysql, sqlite, mssql, pgsql, oracle(目前仅支持mysql,pgsql) Role string // (可选,默认为master)数据库的角色,用于主从操做分离,至少须要有一个master,参数值:master, slave Charset string // (可选,默认为 utf-8)编码,默认为 utf-8 Priority int // (可选)用于负载均衡的权重计算,当集群中只有一个节点时,权重没有任何意义 Linkinfo string // (可选)自定义连接信息,当该字段被设置值时,以上连接字段(Host,Port,User,Pass,Name)将失效(该字段是一个扩展功能,参考sql.Open参数) }
其中,Map和List用于数据表记录操做,分别对应一条数据表记录和数据表记录列表;Config、ConfigGroup及ConfigNode用于数据库配置管理,ConfigNode用于存储一个数据库节点信息,ConfigGroup用于管理多个数据库节点组成的配置分组(通常一个分组对应一个业务数据库集群),Config用于管理多个ConfigGroup配置分组。sql
gdb主要特色:数据库
特别说明,gdb的配置管理最大的特色是,(同一进程中)全部的数据库集群信息都使用同一个配置管理模块进行统一维护,不一样业务的数据库集群配置使用不一样的分组名称进行配置和获取。数据结构
数据库配置管理方法列表:oracle
// 添加一个数据库节点到指定的分组中 func AddConfigNode(group string, node ConfigNode) // 添加一个配置分组到数据库配置管理中(同名覆盖) func AddConfigGroup(group string, nodes ConfigGroup) // 添加一个数据库节点到默认的分组中(默认为default,可修改) func AddDefaultConfigNode(node ConfigNode) // 添加一个配置分组到数据库配置管理中(默认分组为default,可修改) func AddDefaultConfigGroup(nodes ConfigGroup) // 设置数据库配置为定义的配置信息 func SetConfig(c Config) // 设置默认的分组名称 func SetDefaultGroup(groupName string)
默认分组表示,若是获取数据库对象时不指定配置分组名称,那么gdb默认读取的配置分组。例如:gdb.Instance()
可获取一个默认分组的数据库单例对象。负载均衡
简单的作法,咱们能够经过gdb包的SetConfig
配置管理方法进行自定义的数据库全局配置,例如:框架
gdb.SetConfig(gdb.Config { "default" : gdb.ConfigGroup { gdb.ConfigNode { Host : "127.0.0.1", Port : "3306", User : "root", Pass : "123456", Name : "test", Type : "mysql", Role : "master", Priority : 100, }, gdb.ConfigNode { Host : "127.0.0.2", Port : "3306", User : "root", Pass : "123456", Name : "test", Type : "mysql", Role : "master", Priority : 100, }, }, })
固然,gdb支持配置文件进行配置,这样也便于项目的配置管理,具体请参见【ORM高级用法】章节。
gdb数据库操做的方法比较多,具体详见godoc,如下仅对一些经常使用的方法进行介绍。
// SQL操做方法,返回原生的标准库sql对象 Query(query string, args ...interface{}) (*sql.Rows, error) Exec(query string, args ...interface{}) (sql.Result, error) Prepare(query string) (*sql.Stmt, error) // 数据表记录查询: // 查询单条记录、查询多条记录、查询单个字段值(链式操做同理) GetAll(query string, args ...interface{}) (List, error) GetOne(query string, args ...interface{}) (Map, error) GetValue(query string, args ...interface{}) (interface{}, error) // 开启事务操做 Begin() (*Tx, error) // 数据单条操做 Insert(table string, data Map) (sql.Result, error) Replace(table string, data Map) (sql.Result, error) Save(table string, data Map) (sql.Result, error) // 数据批量操做 BatchInsert(table string, list List, batch int) (sql.Result, error) BatchReplace(table string, list List, batch int) (sql.Result, error) BatchSave(table string, list List, batch int) (sql.Result, error) // 数据修改/删除 Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) // 建立链式操做对象(Table为From的别名) Table(tables string) (*DbOp) From(tables string) (*DbOp) // 关闭数据库 Close() error
须要说明一下Insert/Replace/Save三者的区别(BatchInsert/BatchReplace/BatchSave同理):
gdb提供简便灵活的链式操做接口,经过数据库对象的db.Table/db.From方法或者事务对象的tx.Table/tx.From方法基于指定的数据表返回一个链式操做对象DbOp,该对象能够执行如下方法(具体方法说明请参考API文档)。
func LeftJoin(joinTable string, on string) (*DbOp) func RightJoin(joinTable string, on string) (*DbOp) func InnerJoin(joinTable string, on string) (*DbOp) func Fields(fields string) (*DbOp) func Limit(start int, limit int) (*DbOp) func Data(data interface{}) (*DbOp) func Batch(batch int) *DbOp func Where(where string, args...interface{}) (*DbOp) func GroupBy(groupby string) (*DbOp) func OrderBy(orderby string) (*DbOp) func Insert() (sql.Result, error) func Replace() (sql.Result, error) func Save() (sql.Result, error) func Update() (sql.Result, error) func Delete() (sql.Result, error) func Select() (List, error) func All() (List, error) func One() (Map, error) func Value() (interface{}, error)
https://gitee.com/johng/gf/bl...
获取ORM单例对象
// 获取默认配置的数据库对象(配置名称为"default") db, err := gdb.Instance() // 获取配置分组名称为"user-center"的数据库对象 db, err := gdb.Instance("user-center")
数据写入
r, err := db.Insert("user", gdb.Map { "name": "john", })
数据查询(列表)
list, err := db.GetAll("select * from user limit 2")
数据查询(单条)
one, err := db.GetOne("select * from user limit 2") // 或者 one, err := db.GetOne("select * from user where uid=1000")
数据保存
r, err := db.Save("user", gdb.Map { "uid" : 1, "name" : "john", })
批量操做
// BatchInsert/BatchReplace/BatchSave 同理 _, err := db.BatchInsert("user", gdb.List { {"name": "john_1"}, {"name": "john_2"}, {"name": "john_3"}, {"name": "john_4"}, }, 10)
数据更新/删除
// db.Update/db.Delete 同理 r, err := db.Update("user", gdb.Map {"name": "john"}, "uid=?", 10000) r, err := db.Update("user", "name='john'", "uid=10000") r, err := db.Update("user", "name=?", "uid=?", "john", 10000)
注意,参数域支持并建议使用预处理模式进行输入,避免SQL注入风险。
链式查询
// 查询多条记录并使用Limit分页 r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*, ud.site").Where("u.uid > ?", 1).Limit(0, 10).Select() // 查询符合条件的单条记录(第一条) r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.site").Where("u.uid=?", 1).One() // 查询字段值 r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("ud.site").Where("u.uid=?", 1).Value() // 分组及排序 r, err := db.Table("user u").LeftJoin("user_detail ud", "u.uid=ud.uid").Fields("u.*,ud.city").GroupBy("city").OrderBy("register_time asc").Select()
链式更新/删除
// 更新 r, err := db.Table("user").Data(gdb.Map{"name" : "john2"}).Where("name=?", "john").Update() r, err := db.Table("user").Data("name='john3'").Where("name=?", "john2").Update() // 删除 r, err := db.Table("user").Where("uid=?", 10).Delete()
链式写入/保存
r, err := db.Table("user").Data(gdb.Map{"name": "john"}).Insert() r, err := db.Table("user").Data(gdb.Map{"uid": 10000, "name": "john"}).Replace() r, err := db.Table("user").Data(gdb.Map{"uid": 10001, "name": "john"}).Save()
链式批量写入
r, err := db.Table("user").Data(gdb.List{ {"name": "john_1"}, {"name": "john_2"}, {"name": "john_3"}, {"name": "john_4"}, }).Insert()
能够指定批量操做中分批写入数据库的每批次写入条数数量:
r, err := db.Table("user").Data(gdb.List{ {"name": "john_1"}, {"name": "john_2"}, {"name": "john_3"}, {"name": "john_4"}, }).Batch(2).Insert()
链式批量保存
r, err := db.Table("user").Data(gdb.List{ {"uid":10000, "name": "john_1"}, {"uid":10001, "name": "john_2"}, {"uid":10002, "name": "john_3"}, {"uid":10003, "name": "john_4"}, }).Save()
开启事务操做能够经过执行db.Begin
方法,该方法返回事务的操做对象,类型为*gdb.Tx
,经过该对象执行后续的数据库操做,并可经过tx.Commit
提交修改,或者经过tx.Rollback
回滚修改。
开启事务操做
if tx, err := db.Begin(); err == nil { fmt.Println("开启事务操做") }
事务操做对象能够执行全部db对象的方法,具体请参考API文档。
事务回滚操做
if tx, err := db.Begin(); err == nil { r, err := tx.Save("user", gdb.Map{ "uid" : 1, "name" : "john", }) tx.Rollback() fmt.Println(r, err) }
事务提交操做
if tx, err := db.Begin(); err == nil { r, err := tx.Save("user", gdb.Map{ "uid" : 1, "name" : "john", }) tx.Commit() fmt.Println(r, err) }
事务链式操做
事务操做对象仍然能够经过tx.Table
或者tx.From
方法返回一个链式操做的对象,该对象与db.Table
或者db.From
方法返回值相同,只不过数据库操做在事务上执行,可提交或回滚。
if tx, err := db.Begin(); err == nil { r, err := tx.Table("user").Data(gdb.Map{"uid":1, "name": "john_1"}).Save() tx.Commit() fmt.Println(r, err) }
其余链式操做请参考上述链式操做章节。