orm

package module
v2.0.0+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 31, 2017 License: Apache-2.0 Imports: 12 Imported by: 2

README

orm

bysir-zl/rom is a supported 是一个golang编写支持的 存json与模拟join 的orm

使用 Usage

go get github.com/bysir-zl/orm

下面是一个demo+注解

package tests
import (
	"github.com/bysir-zl/bygo/util"
	"github.com/bysir-zl/orm"
	"log"
	"testing"
)
type User struct {
	orm string `table:"user" connect:"default" json:"-"`

	Id         int    `orm:"col(id);pk(auto);" json:"id"`
	Name       string `orm:"col(name)" json:"name"`
	Sex        bool `orm:"col(sex)" json:"sex"`
	Role_ids   []int `orm:"col(role_ids);tran(json)" json:"role_ids"`
	RoleId     int `orm:"col(role_id)"  json:"stime"`
	Created_at string `orm:"col(created_at);auto(insert,time)"  json:"stime"`
	Updated_at string `orm:"col(updated_at);auto(insert|update,time);tran(time)" json:"itime"`
	RoleRaw *Role `orm:"col(role_raw);tran(json)"`
}

type Role struct {
	orm string `table:"role" connect:"default" json:"-"`

	Id   int    `orm:"col(id);pk(auto);" json:"id"`
	Name string `orm:"col(name)" json:"name"`
}

func TestInsert(t *testing.T) {
	test := User{
		Name:"bysir",
		RoleId:1,
		Role_ids:[]int{1,2,3},
		Sex:true,
		RoleRaw:&Role{
			Name:"inJson",
			Id:  1,
		},
	}
	// 你可能会注意到RoleRaw和Role_ids字段是一个结构体, 他们会自动在入库的时候序列化为json串,
	// 在出库的时候自动反序列化为结构体, 这只需要在你的model字段上添加一个 tran(json) Tag, 内置两个转换器是json和time,
	// 要自定义你只需要实现一个转换器(Translator)并RegisterTranslator(name,Translator)

	err := orm.Model(&test).Insert(&test)
	if err != nil {
		t.Error(err)    
	}
}

// 别忘了配置Db与注册模型
func init() {
    // 开启debug会打印sql语句
	orm.Debug = true

	orm.RegisterDb("default", "mysql", "root:@tcp(localhost:3306)/test")
	orm.RegisterModel(new(User))
	orm.RegisterModel(new(Role))
}

高级用法 Advanced

实现模拟数据库join语法, 为什么不直接用join? 个人不喜欢而已 ;)

假如你要实现根据一个role_id关联到role表的数据的话,你可能会想到用join, 现在还有一个前端实现: link, orm会帮你自动的读取关联模型,

看看下面这个model

type User struct {
	orm string `table:"user" connect:"default" json:"-"`

	Id         int    `orm:"col(id);pk(auto);" json:"id"`
	Name       string `orm:"col(name)" json:"name"`
	Role_ids   []int `orm:"col(role_ids);tran(json)" json:"role_ids"`
	RoleId     int `orm:"col(role_id)"  json:"stime"`

	Role   *Role `orm:"link(RoleId,id)"`
	Roles []Role `orm:"link(Role_ids,id)"`
}

这样使用link

func TestSelect(t *testing.T) {
	us := []User{}
	
	// 需要显示的指定你要link的字段
	_, err := orm.Model(&us).
		Link("Role", "", []string{"name"}).
		Link("Roles", "", nil).
		Select(&us)
	if err != nil {
		t.Error(err)
	}
	log.Printf("role    %+v", ts[0].Role) // 一个role
	log.Printf("roles   %+v", ts[0].Roles)// role的slice
}

就是这么简单, 当查询多个Role的时候, orm还会自动优化sql, 解决sql n+1 问题

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	Debug = false
)
View Source
var DefaultDecoder = func(prtModel interface{}) ModelInfo {
	tag := "orm"
	fInfo := DecodeStruct(prtModel)
	table := Field2TagMap(fInfo, "table")["orm"]
	connect := Field2TagMap(fInfo, "connect")["orm"]
	fieldMap := Field2TagMap(fInfo, tag)
	fieldTyp := FieldType(fInfo)

	field2Db := map[string]string{}
	autoPk := ""
	autoFields := map[string]Auto{}
	trans := map[string]Tran{}
	links := map[string]Link{}
	for field, db := range fieldMap {
		columnTags := DecodeColumn(db)
		for key, values := range columnTags {
			switch key {
			case "pk":
				if len(values) >= 1 {
					if values[0] == "auto" {
						autoPk = field
					}
				}
			case "col":
				if len(values) >= 1 {
					field2Db[field] = values[0]
				}
			case "tran":
				if len(values) >= 1 {
					trans[field] = Tran{
						Typ: values[0],
					}
				}
			case "auto":
				if len(values) >= 2 {
					autoFields[field] = Auto{
						When: values[0],
						Typ:  values[1],
					}
				}
			case "link":
				if len(values) >= 2 {
					links[field] = Link{
						SelfKey: values[0],
						LinkKey: values[1],
					}
				}
			}
		}
	}

	m := ModelInfo{
		FieldMap:    field2Db,
		AutoPk:      autoPk,
		Table:       table,
		ConnectName: connect,
		AutoFields:  autoFields,
		FieldTyp:    fieldTyp,
		Trans:       trans,
		Links:       links,
	}

	return m
}

Functions

func DecodeColumn

func DecodeColumn(dbData string) map[string][]string

func DecodeStruct

func DecodeStruct(prtStruct interface{}) map[string]FieldInfo

func EncodeTag

func EncodeTag(tag string) (data map[string]string)

func ExecSql

func ExecSql(sql string, args ...interface{}) (affectCount int64, lastInsertId int64, err error)

func Field2TagMap

func Field2TagMap(fieldInfo map[string]FieldInfo, tag string) map[string]string

返回指定tag的string

func FieldType

func FieldType(fieldInfo map[string]FieldInfo) map[string]reflect.Type

func Insert

func Insert(mo interface{}) (err error)

func QuerySql

func QuerySql(sql string, args ...interface{}) (has bool, data []map[string]interface{}, err error)

func RegisterDb

func RegisterDb(connect, driver, link string)

default,mysql,xxx:xxx

func RegisterModel

func RegisterModel(prtModel interface{})

注册模型, 将字段对应写入map

func RegisterModelCustom

func RegisterModelCustom(prtModel interface{}, decoder func(prtModel interface{}) ModelInfo)

func RegisterTranslator

func RegisterTranslator(name string, translator Translator)

func UnDuplicate

func UnDuplicate(src []interface{}) []interface{}

去重, 但是不能去除 int64 与 int 的重复 ...

Types

type Auto

type Auto struct {
	When string // 当什么时候自动更新字段
	Typ  string // 目前只支持time的自动更新
}

type Column

type Column struct {
	Name string
	Pk   string // "":不是pk, auto:自增pk
	Tran Tran   // 自动转换规则 json:string转换为field
	Auto Auto
	Link Link
}

type Config

type Config map[string]Connect

type Connect

type Connect struct {
	Driver string `json:"driver"`
	// USER:PWD@tcp(HOST:PORT)/DBNAME
	Url string `json:"url"`
}

func (*Connect) SqlString

func (p *Connect) SqlString() string

func (*Connect) String

func (p *Connect) String() string

type DbDriverMysql

type DbDriverMysql struct {
	// contains filtered or unexported fields
}

func Singleton

func Singleton(connect *Connect) (*DbDriverMysql, error)

单例取出db 并返回自己 err 是打开数据库连接的错误

func (*DbDriverMysql) Exec

func (p *DbDriverMysql) Exec(sql string, args ...interface{}) (affectCount int64, lastInsertId int64, err error)

执行不带返回的查询(写) 返回insertId,

func (*DbDriverMysql) Query

func (p *DbDriverMysql) Query(sql string, args ...interface{}) (data []map[string]interface{}, err error)

带返回值的查询,(读) 返回一个[]map[string]interface 对应多行键值对

type FieldInfo

type FieldInfo struct {
	Name         string
	Typ          reflect.Type
	CanInterface bool
	Tags         map[string]string
}

type InOneSql

type InOneSql struct {
	Table      string
	WhereField string
}

能组装成一个条sql的

func (*InOneSql) String

func (p *InOneSql) String() string

type JsonTran

type JsonTran struct{}

func (*JsonTran) Input

func (p *JsonTran) Input(fieldName string, fieldType reflect.Type, input interface{}) (result interface{}, err error)

func (*JsonTran) Output

func (p *JsonTran) Output(fieldName string, fieldType reflect.Type, output interface{}) (result interface{}, err error)
type Link struct {
	SelfKey string // 自身的字段
	LinkKey string // 要连接的对象的字段
}

type ModelInfo

type ModelInfo struct {
	FieldMap    map[string]string       // struct => db
	FieldTyp    map[string]reflect.Type // 字段类型
	Table       string                  // table name
	ConnectName string                  // connect name
	AutoPk      string                  // 自增主键
	AutoFields  map[string]Auto
	Trans       map[string]Tran
	Links       map[string]Link
}

type Page

type Page struct {
	Total     int64 `json:"total,omitempty"`
	PageTotal int   `json:"page_total,omitempty"`
	Page      int   `json:"page,omitempty"`
	PageSize  int   `json:"page_size,omitempty"`
}
type PreLink struct {
	Args   []interface{} // 参数
	Column []string      // 要查询的字段
	Model  interface{}   // 要查询的模型(一个struct)
	ArgKey string        // 要连接的字段
}

type ResultKeyMap

type ResultKeyMap struct {
	OneSql string
	Value  string // 由于数据库读出来的值可能和存放link值类型不对应(在第一个orm时会转换类型), 这里就全部转换为string去对应
}

type TimeTran

type TimeTran struct{}

func (*TimeTran) Input

func (p *TimeTran) Input(fieldName string, fieldType reflect.Type, input interface{}) (result interface{}, err error)

func (*TimeTran) Output

func (p *TimeTran) Output(fieldName string, fieldType reflect.Type, output interface{}) (result interface{}, err error)

type Tran

type Tran struct {
	Typ string // 转换类型,目前支持 json(obj=>string), time(int=>string)
}

type Translator

type Translator interface {
	Input(fieldName string, fieldType reflect.Type, input interface{}) (interface{}, error) // 入库
	Output(fieldName string, field reflect.Type, output interface{}) (interface{}, error)   // 出库
}

type WithModel

type WithModel struct {
	WithOutModel
	// contains filtered or unexported fields
}

func Model

func Model(mo interface{}) *WithModel

指定模型的入口

func (*WithModel) Connect

func (p *WithModel) Connect(connect string) *WithModel

func (*WithModel) Fields

func (p *WithModel) Fields(fields ...string) *WithModel

在更新或者查找时的字段

func (*WithModel) FromDbData

func (p *WithModel) FromDbData(isSlice bool, result []map[string]interface{}, ptrSliceModel interface{})

将从db里取得的map赋值到model里

func (*WithModel) GetAutoSetField

func (p *WithModel) GetAutoSetField(method string) (needSet map[string]interface{}, err error)

取得在method操作时需要自动填充的字段与值

func (*WithModel) Insert

func (p *WithModel) Insert(prtModel interface{}) (err error)

插入一个模型

func (*WithModel) Limit

func (p *WithModel) Limit(offset, size int) *WithModel

limit

func (p *WithModel) Link(field string, extCondition string, columns []string) *WithModel

连接对象

func (*WithModel) Select

func (p *WithModel) Select(ptrSliceModel interface{}) (has bool, err error)

查找一列或多列 可以传入切片引用或者一个对象引用 eg: d := &[]User{}, d := &User{}

func (*WithModel) Table

func (p *WithModel) Table(table string) *WithModel

func (*WithModel) Where

func (p *WithModel) Where(condition string, args ...interface{}) *WithModel

condition 条件 eg: `id = ?`. ?是占位符, 参数通过args传递 args 参数 eg: `1,2,3`. 注意 只能是基础类型, 并不支持切片等, 有多个参数请展开

func (*WithModel) WhereIn

func (p *WithModel) WhereIn(condition string, args ...interface{}) *WithModel

condition 条件 eg: `id in (?)`. 注意 必须有(?)占位符, 这其实只是一个帮你拼?占位符的语法糖 args 参数 eg: `1,2,3`. 注意 只能是基础类型, 并不支持切片等, 有多个参数请展开

type WithOutModel

type WithOutModel struct {
	// contains filtered or unexported fields
}

func Table

func Table(table string) *WithOutModel

不指定模型的入口

func (*WithOutModel) Connect

func (p *WithOutModel) Connect(connect string) *WithOutModel

func (*WithOutModel) Delete

func (p *WithOutModel) Delete() (affect int64, err error)

删除, 注意必须要有where条件

func (*WithOutModel) ExecSql

func (p *WithOutModel) ExecSql(sql string, args ...interface{}) (affectCount int64, lastInsertId int64, err error)

func (*WithOutModel) Fields

func (p *WithOutModel) Fields(fields ...string) *WithOutModel

func (*WithOutModel) First

func (p *WithOutModel) First() (result map[string]interface{}, has bool, err error)

查找并返回一个

func (*WithOutModel) GetTable

func (p *WithOutModel) GetTable() string

func (*WithOutModel) Insert

func (p *WithOutModel) Insert(saveData map[string]interface{}) (id int64, err error)

插入

func (*WithOutModel) Limit

func (p *WithOutModel) Limit(offset, size int) *WithOutModel

func (*WithOutModel) QuerySql

func (p *WithOutModel) QuerySql(sql string, args ...interface{}) (result []map[string]interface{}, err error)

func (*WithOutModel) Select

func (p *WithOutModel) Select() (result []map[string]interface{}, has bool, err error)

查找

func (*WithOutModel) Table

func (p *WithOutModel) Table(table string) *WithOutModel

func (*WithOutModel) Update

func (p *WithOutModel) Update(saveData map[string]interface{}) (aff int64, err error)

更新, 注意必须要有where条件

func (*WithOutModel) Where

func (p *WithOutModel) Where(condition string, args ...interface{}) *WithOutModel

func (*WithOutModel) WhereIn

func (p *WithOutModel) WhereIn(condition string, args ...interface{}) *WithOutModel

condition 条件 eg: `id in (?)`. 注意 必须有(?)占位符, 这其实只是一个帮你拼?占位符的语法糖 args 参数 eg: `1,2,3`. 注意 只能是基础类型, 并不支持切片等, 有多个参数请展开

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL