改进ORM操作

This commit is contained in:
John
2018-04-20 23:23:42 +08:00
parent 1b481b6747
commit 16be73a5c1
6 changed files with 370 additions and 297 deletions

View File

@ -15,6 +15,7 @@ import (
"gitee.com/johng/gf/g/util/grand"
_ "github.com/lib/pq"
_ "github.com/go-sql-driver/mysql"
"gitee.com/johng/gf/g/util/gconv"
)
const (
@ -65,8 +66,8 @@ type Link interface {
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error)
// 创建链式操作对象(Table为From的别名)
Table(tables string) (*DbOp)
From(tables string) (*DbOp)
Table(tables string) (*Model)
From(tables string) (*Model)
// 关闭数据库操作对象
Close() error
@ -193,12 +194,8 @@ func getConfigNodeByPriority (cg *ConfigGroup) *ConfigNode {
func newDb (masterNode *ConfigNode, slaveNode *ConfigNode) (*Db, error) {
var link Link
switch masterNode.Type {
case "mysql":
link = Link(&dbmysql{})
case "pgsql":
link = Link(&dbpgsql{})
case "mysql": link = Link(&dbmysql{})
case "pgsql": link = Link(&dbpgsql{})
default:
return nil, errors.New(fmt.Sprintf("unsupported db type '%s'", masterNode.Type))
}
@ -226,3 +223,35 @@ func newDb (masterNode *ConfigNode, slaveNode *ConfigNode) (*Db, error) {
}, nil
}
// 将结果列表按照指定的字段值做map[string]Map
func (list List) ToStringMap(key string) map[string]Map {
m := make(map[string]Map)
for _, item := range list {
if v, ok := item[key]; ok {
m[gconv.String(v)] = item
}
}
return m
}
// 将结果列表按照指定的字段值做map[int]Map
func (list List) ToIntMap(key string) map[int]Map {
m := make(map[int]Map)
for _, item := range list {
if v, ok := item[key]; ok {
m[gconv.Int(v)] = item
}
}
return m
}
// 将结果列表按照指定的字段值做map[uint]Map
func (list List) ToUintMap(key string) map[uint]Map {
m := make(map[uint]Map)
for _, item := range list {
if v, ok := item[key]; ok {
m[gconv.Uint(v)] = item
}
}
return m
}

View File

@ -128,6 +128,24 @@ func (db *Db) GetValue(query string, args ...interface{}) (interface{}, error) {
return nil, nil
}
// 数据表查询其中tables可以是多个联表查询语句这种查询方式较复杂建议使用链式操作
func (db *Db) Select(tables, fields string, condition interface{}, groupBy, orderBy string, first, limit int, args ... interface{}) (List, error) {
s := fmt.Sprintf("SELECT %s FROM %s ", fields, tables)
if condition != nil {
s += fmt.Sprintf("WHERE %s ", db.formatCondition(condition))
}
if len(groupBy) > 0 {
s += fmt.Sprintf("GROUP BY %s ", groupBy)
}
if len(orderBy) > 0 {
s += fmt.Sprintf("ORDER BY %s ", orderBy)
}
if limit > 0 {
s += fmt.Sprintf("LIMIT %d,%d ", first, limit)
}
return db.GetAll(s, args ... )
}
// sql预处理执行完成后调用返回值sql.Stmt.Exec完成sql操作
// 记得调用sql.Stmt.Close关闭操作对象
func (db *Db) Prepare(query string) (*sql.Stmt, error) {

View File

@ -1,281 +0,0 @@
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
package gdb
import (
"fmt"
"errors"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
// 数据库链式操作对象
type DbOp struct {
tx *Tx // 数据库事务对象
db *Db // 数据库操作对象
tables string // 数据库操作表
fields string // 操作字段
where string // 操作条件
whereArgs []interface{} // 操作条件参数
groupBy string // 分组语句
orderBy string // 排序语句
start int // 分页开始
limit int // 分页条数
data interface{} // 操作记录(支持Map/List/string类型)
batch int // 批量操作条数
}
// 链式操作,数据表字段,可支持多个表,以半角逗号连接
func (db *Db) Table(tables string) (*DbOp) {
return &DbOp {
db : db,
tables : tables,
}
}
// 链式操作,数据表字段,可支持多个表,以半角逗号连接
func (db *Db) From(tables string) (*DbOp) {
return db.Table(tables)
}
// (事务)链式操作,数据表字段,可支持多个表,以半角逗号连接
func (tx *Tx) Table(tables string) (*DbOp) {
return &DbOp {
tx : tx,
tables : tables,
}
}
// (事务)链式操作,数据表字段,可支持多个表,以半角逗号连接
func (tx *Tx) From(tables string) (*DbOp) {
return tx.Table(tables)
}
// 链式操作,左联表
func (op *DbOp) LeftJoin(joinTable string, on string) (*DbOp) {
op.tables += fmt.Sprintf(" LEFT JOIN %s ON (%s)", joinTable, on)
return op
}
// 链式操作,右联表
func (op *DbOp) RightJoin(joinTable string, on string) (*DbOp) {
op.tables += fmt.Sprintf(" RIGHT JOIN %s ON (%s)", joinTable, on)
return op
}
// 链式操作,内联表
func (op *DbOp) InnerJoin(joinTable string, on string) (*DbOp) {
op.tables += fmt.Sprintf(" INNER JOIN %s ON (%s)", joinTable, on)
return op
}
// 链式操作,查询字段
func (op *DbOp) Fields(fields string) (*DbOp) {
op.fields = fields
return op
}
// 链式操作condition支持string & gdb.Map
func (op *DbOp) Where(where interface{}, args...interface{}) (*DbOp) {
op.where = op.db.formatCondition(where)
op.whereArgs = args
return op
}
// 链式操作group by
func (op *DbOp) GroupBy(groupBy string) (*DbOp) {
op.groupBy = groupBy
return op
}
// 链式操作order by
func (op *DbOp) OrderBy(orderBy string) (*DbOp) {
op.orderBy = orderBy
return op
}
// 链式操作limit
func (op *DbOp) Limit(start int, limit int) (*DbOp) {
op.start = start
op.limit = limit
return op
}
// 链式操作,操作数据记录项
func (op *DbOp) Data(data interface{}) (*DbOp) {
op.data = data
return op
}
// 链式操作, CURD - Insert/BatchInsert
func (op *DbOp) Insert() (sql.Result, error) {
// 批量操作
if list, ok := op.data.(List); ok {
batch := 10
if op.batch > 0 {
batch = op.batch
}
if op.tx == nil {
return op.db.BatchInsert(op.tables, list, batch)
} else {
return op.tx.BatchInsert(op.tables, list, batch)
}
}
// 记录操作
if op.data == nil {
return nil, errors.New("inserting into table with empty data")
}
if dataMap, ok := op.data.(Map); ok {
if op.tx == nil {
return op.db.Insert(op.tables, dataMap)
} else {
return op.tx.Insert(op.tables, dataMap)
}
}
return nil, errors.New("inserting into table with invalid data type")
}
// 链式操作, CURD - Replace/BatchReplace
func (op *DbOp) Replace() (sql.Result, error) {
// 批量操作
if list, ok := op.data.(List); ok {
batch := 10
if op.batch > 0 {
batch = op.batch
}
if op.tx == nil {
return op.db.BatchReplace(op.tables, list, batch)
} else {
return op.tx.BatchReplace(op.tables, list, batch)
}
}
// 记录操作
if op.data == nil {
return nil, errors.New("replacing into table with empty data")
}
if dataMap, ok := op.data.(Map); ok {
if op.tx == nil {
return op.db.Insert(op.tables, dataMap)
} else {
return op.tx.Insert(op.tables, dataMap)
}
}
return nil, errors.New("replacing into table with invalid data type")
}
// 链式操作, CURD - Save/BatchSave
func (op *DbOp) Save() (sql.Result, error) {
// 批量操作
if list, ok := op.data.(List); ok {
batch := 10
if op.batch > 0 {
batch = op.batch
}
if op.tx == nil {
return op.db.BatchSave(op.tables, list, batch)
} else {
return op.tx.BatchSave(op.tables, list, batch)
}
}
// 记录操作
if op.data == nil {
return nil, errors.New("saving into table with empty data")
}
if dataMap, ok := op.data.(Map); ok {
if op.tx == nil {
return op.db.Save(op.tables, dataMap)
} else {
return op.tx.Save(op.tables, dataMap)
}
}
return nil, errors.New("saving into table with invalid data type")
}
// 链式操作, CURD - Update
func (op *DbOp) Update() (sql.Result, error) {
if op.data == nil {
return nil, errors.New("updating table with empty data")
}
if op.tx == nil {
return op.db.Update(op.tables, op.data, op.where, op.whereArgs ...)
} else {
return op.tx.Update(op.tables, op.data, op.where, op.whereArgs ...)
}
}
// 链式操作, CURD - Delete
func (op *DbOp) Delete() (sql.Result, error) {
if op.where == "" {
return nil, errors.New("where is required while deleting")
}
if op.tx == nil {
return op.db.Delete(op.tables, op.where, op.whereArgs...)
} else {
return op.tx.Delete(op.tables, op.where, op.whereArgs...)
}
}
// 设置批处理的大小
func (op *DbOp) Batch(batch int) *DbOp {
op.batch = batch
return op
}
// 链式操作select
func (op *DbOp) Select() (List, error) {
if op.fields == "" {
op.fields = "*"
}
s := fmt.Sprintf("SELECT %s FROM %s", op.fields, op.tables)
if op.where != "" {
s += " WHERE " + op.where
}
if op.groupBy != "" {
s += " GROUP BY " + op.groupBy
}
if op.orderBy != "" {
s += " ORDER BY " + op.orderBy
}
if op.limit != 0 {
s += fmt.Sprintf(" LIMIT %d, %d", op.start, op.limit)
}
if op.tx == nil {
return op.db.GetAll(s, op.whereArgs...)
} else {
return op.tx.GetAll(s, op.whereArgs...)
}
}
// 链式操作,查询所有记录
func (op *DbOp) All() (List, error) {
return op.Select()
}
// 链式操作,查询单条记录
func (op *DbOp) One() (Map, error) {
list, err := op.All()
if err != nil {
return nil, err
}
if len(list) > 0 {
return list[0], nil
}
return nil, nil
}
// 链式操作,查询字段值
func (op *DbOp) Value() (interface{}, error) {
one, err := op.One()
if err != nil {
return "", err
}
for _, v := range one {
return v, nil
}
return "", nil
}

304
g/database/gdb/gdb_model.go Normal file
View File

@ -0,0 +1,304 @@
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
package gdb
import (
"fmt"
"errors"
"database/sql"
"gitee.com/johng/gf/g/util/gconv"
_ "github.com/go-sql-driver/mysql"
)
// 数据库链式操作模型对象
type Model struct {
tx *Tx // 数据库事务对象
db *Db // 数据库操作对象
tables string // 数据库操作表
fields string // 操作字段
where string // 操作条件
whereArgs []interface{} // 操作条件参数
groupBy string // 分组语句
orderBy string // 排序语句
start int // 分页开始
limit int // 分页条数
data interface{} // 操作记录(支持Map/List/string类型)
batch int // 批量操作条数
}
// 链式操作,数据表字段,可支持多个表,以半角逗号连接
func (db *Db) Table(tables string) (*Model) {
return &Model {
db : db,
tables : tables,
}
}
// 链式操作,数据表字段,可支持多个表,以半角逗号连接
func (db *Db) From(tables string) (*Model) {
return db.Table(tables)
}
// (事务)链式操作,数据表字段,可支持多个表,以半角逗号连接
func (tx *Tx) Table(tables string) (*Model) {
return &Model {
tx : tx,
tables : tables,
}
}
// (事务)链式操作,数据表字段,可支持多个表,以半角逗号连接
func (tx *Tx) From(tables string) (*Model) {
return tx.Table(tables)
}
// 链式操作,左联表
func (md *Model) LeftJoin(joinTable string, on string) (*Model) {
md.tables += fmt.Sprintf(" LEFT JOIN %s ON (%s)", joinTable, on)
return md
}
// 链式操作,右联表
func (md *Model) RightJoin(joinTable string, on string) (*Model) {
md.tables += fmt.Sprintf(" RIGHT JOIN %s ON (%s)", joinTable, on)
return md
}
// 链式操作,内联表
func (md *Model) InnerJoin(joinTable string, on string) (*Model) {
md.tables += fmt.Sprintf(" INNER JOIN %s ON (%s)", joinTable, on)
return md
}
// 链式操作,查询字段
func (md *Model) Fields(fields string) (*Model) {
md.fields = fields
return md
}
// 链式操作condition支持string & gdb.Map
func (md *Model) Where(where interface{}, args...interface{}) (*Model) {
md.where = md.db.formatCondition(where)
md.whereArgs = args
return md
}
// 链式操作添加AND条件到Where中
func (md *Model) And(where interface{}, args...interface{}) (*Model) {
md.where += " AND " + md.db.formatCondition(where)
md.whereArgs = append(md.whereArgs, args)
return md
}
// 链式操作添加OR条件到Where中
func (md *Model) Or(where interface{}, args...interface{}) (*Model) {
md.where += " OR " + md.db.formatCondition(where)
md.whereArgs = append(md.whereArgs, args)
return md
}
// 链式操作group by
func (md *Model) GroupBy(groupBy string) (*Model) {
md.groupBy = groupBy
return md
}
// 链式操作order by
func (md *Model) OrderBy(orderBy string) (*Model) {
md.orderBy = orderBy
return md
}
// 链式操作limit
func (md *Model) Limit(start int, limit int) (*Model) {
md.start = start
md.limit = limit
return md
}
// 链式操作操作数据记录项可以是string/Map, 也可以是key,value,key,value,...
func (md *Model) Data(data...interface{}) (*Model) {
if len(data) > 1 {
m := make(map[string]interface{})
for i := 0; i < len(data); i += 2 {
m[gconv.String(data[i])] = data[i + 1]
}
md.data = m
} else {
md.data = data[0]
}
return md
}
// 链式操作, CURD - Insert/BatchInsert
func (md *Model) Insert() (sql.Result, error) {
// 批量操作
if list, ok := md.data.(List); ok {
batch := 10
if md.batch > 0 {
batch = md.batch
}
if md.tx == nil {
return md.db.BatchInsert(md.tables, list, batch)
} else {
return md.tx.BatchInsert(md.tables, list, batch)
}
}
// 记录操作
if md.data == nil {
return nil, errors.New("inserting into table with empty data")
}
if dataMap, ok := md.data.(Map); ok {
if md.tx == nil {
return md.db.Insert(md.tables, dataMap)
} else {
return md.tx.Insert(md.tables, dataMap)
}
}
return nil, errors.New("inserting into table with invalid data type")
}
// 链式操作, CURD - Replace/BatchReplace
func (md *Model) Replace() (sql.Result, error) {
// 批量操作
if list, ok := md.data.(List); ok {
batch := 10
if md.batch > 0 {
batch = md.batch
}
if md.tx == nil {
return md.db.BatchReplace(md.tables, list, batch)
} else {
return md.tx.BatchReplace(md.tables, list, batch)
}
}
// 记录操作
if md.data == nil {
return nil, errors.New("replacing into table with empty data")
}
if dataMap, ok := md.data.(Map); ok {
if md.tx == nil {
return md.db.Insert(md.tables, dataMap)
} else {
return md.tx.Insert(md.tables, dataMap)
}
}
return nil, errors.New("replacing into table with invalid data type")
}
// 链式操作, CURD - Save/BatchSave
func (md *Model) Save() (sql.Result, error) {
// 批量操作
if list, ok := md.data.(List); ok {
batch := 10
if md.batch > 0 {
batch = md.batch
}
if md.tx == nil {
return md.db.BatchSave(md.tables, list, batch)
} else {
return md.tx.BatchSave(md.tables, list, batch)
}
}
// 记录操作
if md.data == nil {
return nil, errors.New("saving into table with empty data")
}
if dataMap, ok := md.data.(Map); ok {
if md.tx == nil {
return md.db.Save(md.tables, dataMap)
} else {
return md.tx.Save(md.tables, dataMap)
}
}
return nil, errors.New("saving into table with invalid data type")
}
// 链式操作, CURD - Update
func (md *Model) Update() (sql.Result, error) {
if md.data == nil {
return nil, errors.New("updating table with empty data")
}
if md.tx == nil {
return md.db.Update(md.tables, md.data, md.where, md.whereArgs ...)
} else {
return md.tx.Update(md.tables, md.data, md.where, md.whereArgs ...)
}
}
// 链式操作, CURD - Delete
func (md *Model) Delete() (sql.Result, error) {
if md.where == "" {
return nil, errors.New("where is required while deleting")
}
if md.tx == nil {
return md.db.Delete(md.tables, md.where, md.whereArgs...)
} else {
return md.tx.Delete(md.tables, md.where, md.whereArgs...)
}
}
// 设置批处理的大小
func (md *Model) Batch(batch int) *Model {
md.batch = batch
return md
}
// 链式操作select
func (md *Model) Select() (List, error) {
if md.fields == "" {
md.fields = "*"
}
s := fmt.Sprintf("SELECT %s FROM %s", md.fields, md.tables)
if md.where != "" {
s += " WHERE " + md.where
}
if md.groupBy != "" {
s += " GROUP BY " + md.groupBy
}
if md.orderBy != "" {
s += " ORDER BY " + md.orderBy
}
if md.limit != 0 {
s += fmt.Sprintf(" LIMIT %d, %d", md.start, md.limit)
}
if md.tx == nil {
return md.db.GetAll(s, md.whereArgs...)
} else {
return md.tx.GetAll(s, md.whereArgs...)
}
}
// 链式操作,查询所有记录
func (md *Model) All() (List, error) {
return md.Select()
}
// 链式操作,查询单条记录
func (md *Model) One() (Map, error) {
list, err := md.All()
if err != nil {
return nil, err
}
if len(list) > 0 {
return list[0], nil
}
return nil, nil
}
// 链式操作,查询字段值
func (md *Model) Value() (interface{}, error) {
one, err := md.One()
if err != nil {
return "", err
}
for _, v := range one {
return v, nil
}
return "", nil
}

4
g/g.go
View File

@ -4,8 +4,10 @@
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
package g
// 常用map数据结构
type Map map[string]interface{}
// 常用list数据结构
type List []Map

View File

@ -14,6 +14,7 @@ import (
"net/http"
"gitee.com/johng/gf/g/os/glog"
"gitee.com/johng/gf/g/os/gcache"
"gitee.com/johng/gf/g/util/gconv"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/container/gtype"
"gitee.com/johng/gf/g/container/gqueue"
@ -83,16 +84,16 @@ var serverMapping = gmap.NewStringInterfaceMap()
// 获取/创建一个默认配置的HTTP Server(默认监听端口是80)
// 单例模式请保证name的唯一性
func GetServer(names...string) (*Server) {
name := gDEFAULT_SERVER
if len(names) > 0 {
name = names[0]
func GetServer(name...interface{}) (*Server) {
sname := gDEFAULT_SERVER
if len(name) > 0 {
sname = gconv.String(name[0])
}
if s := serverMapping.Get(name); s != nil {
if s := serverMapping.Get(sname); s != nil {
return s.(*Server)
}
s := &Server {
name : name,
name : sname,
methodsMap : make(map[string]bool),
handlerMap : make(HandlerMap),
handlerTree : make(map[string]interface{}),
@ -122,7 +123,7 @@ func GetServer(names...string) (*Server) {
s.methodsMap[v] = true
}
s.SetConfig(defaultServerConfig)
serverMapping.Set(name, s)
serverMapping.Set(sname, s)
return s
}