• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

toyorm: golang orm

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

toyorm

开源软件地址:

https://gitee.com/bigpigeon/toyorm

开源软件介绍:

Toyorm

this is powerful sql orm library for Golang, have some funny features

Build StatuscodecovGo Report CardGoDocJoin the chat



Support database

sqlite3 mysql postgresql

Go version

version go-1.9


A Simple Example

here


Website Example

here


Database connection

import database driver

// if database is mysql_ "github.com/go-sql-driver/mysql"// if database is sqlite3_ "github.com/mattn/go-sqlite3"// when database is postgres_ "github.com/lib/pq"

create a toy

// if database is mysql, make sure your mysql have toyorm_example schematoy, err = toyorm.Open("mysql", "root:@tcp(localhost:3306)/toyorm_example?charset=utf8&parseTime=True")// if database is sqlite3toy,err = toyorm.Open("sqlite3", "toyorm_test.db")// when database is postgrestoy, err = toyorm.Open("postgres", "user=postgres dbname=toyorm sslmode=disable")

Model definition

example
type Extra map[string]interface{}func (e Extra) Scan(value interface{}) error {     switch v := value.(type) {     case string:          return json.Unmarshal([]byte(v), e)     case []byte:          return json.Unmarshal(v, e)     default:          return errors.New("not support type")     }}func (e Extra) Value() (driver.Value, error) {     return json.Marshal(e)}type UserDetail struct {     ID       int  `toyorm:"primary key;auto_increment"`     UserID   uint `toyorm:"index"`     MainPage string     Extra    Extra `toyorm:"type:VARCHAR(1024)"`}type Blog struct {     toyorm.ModelDefault     UserID  uint   `toyorm:"index"`     Title   string `toyorm:"index"`     Content string}type User struct {     toyorm.ModelDefault     Name    string `toyorm:"unique index"`     Age     int     Sex     string     Detail  *UserDetail     Friends []*User     Blog    []Blog}
type translate

if sql type is not match, toyorm will ignore it in Sql Operation

you can use <type:sql_type> field tag to specified their sql type

the following type will auto translate to sql type

Go Typesql type
boolBOOLEAN
int8,int16,int32,uint8,uint16,uint32INTEGER
int64,uint64,int,uintBIGINT
float32,float64FLOAT
stringVARCHAR(255)
time.TimeTIMESTAMP
[]byteVARCHAR(255)
sql.NullBoolBOOLEAN
sql.NullInt64BIGINT
sql.NullFloat64FLOAT
sql.NullStringVARCHAR(255)
sql.RawBytesVARCHAR(255)

special fields

  1. special fields have some process in handlers, do not try to change it type or set it value
Field NameTypeDescription
CreatedAttime.Timegenerate when element be create
UpdatedAttime.Timegenerate when element be update/create
DeletedAt*time.Timedelete mode is soft
Casint(not support for sqlite3)save operation will failure when it's value modified by third party e.g in postgres:cas=1 insert xxx conflict(id) update cas = 2 where cas = 1

field tags

  1. tag format can be <key:value> or <key>

  2. the following is special tag

KeyValueDescription
indexvoid or stringuse for optimization when search condition have this field,if you want make a combined,just set same index name with fields
unique indexvoid or stringhave unique limit index, other same as index
primary keyvoidallow multiple primary key,but some operation not support
-voidignore this field in sql
typestringsql type
columnstringsql column name
auto_incrementvoidrecommend, if your table primary key have auto_increment attribute must add it
autoincrementvoidsame as auto_increment
foreign keyvoidto add foreign key feature when create table
aliasstringchange field name with toyorm
joinstringto select related field when call brick.Join
belong tostringto select related field when call brick.Preload with BelongTo container
one to onestringto select related field when call brick.Preload with OneToOne container
one to manystringto select related field when call brick.Preload with OneToMany container
defaultsrringdefault value in database

other custom TAG will append to end of CREATE TABLE field

Bind models

  1. model kind must be a struct or a point with struct

  2. the model is what information that toyorm know about the table

brick := toy.Model(&User{})// orbrick := toy.Model(User{})

Sql Operation


create table

var err error_, err = toy.Model(&User{}).Debug().CreateTable()// CREATE TABLE user (id BIGINT AUTO_INCREMENT,created_at TIMESTAMP NULL,updated_at TIMESTAMP NULL,deleted_at TIMESTAMP NULL,name VARCHAR(255),age BIGINT ,sex VARCHAR(255) , PRIMARY KEY(id))// CREATE INDEX idx_user_deletedat ON user(deleted_at)// CREATE UNIQUE INDEX udx_user_name ON user(name)_, err =toy.Model(&UserDetail{}).Debug().CreateTable()// CREATE TABLE user_detail (id BIGINT AUTO_INCREMENT,user_id BIGINT,main_page Text,extra VARCHAR(1024), PRIMARY KEY(id))// CREATE INDEX idx_user_detail_userid ON user_detail(user_id)_, err =toy.Model(&Blog{}).Debug().CreateTable()// CREATE TABLE blog (id BIGINT AUTO_INCREMENT,created_at TIMESTAMP NULL,updated_at TIMESTAMP NULL,deleted_at TIMESTAMP NULL,user_id BIGINT,title VARCHAR(255),content VARCHAR(255) , PRIMARY KEY(id))// CREATE INDEX idx_blog_deletedat ON blog(deleted_at)// CREATE INDEX idx_blog_userid ON blog(user_id)// CREATE INDEX idx_blog_title ON blog(title)

drop table

var err error_, err =toy.Model(&User{}).Debug().DropTable()// DROP TABLE user_, err =toy.Model(&UserDetail{}).Debug().DropTable()// DROP TABLE user_detail_, err =toy.Model(&Blog{}).Debug().DropTable()// DROP TABLE blog

insert/save data

// insert with autoincrement will set id to source data

user := &User{    Name: "bigpigeon",    Age:  18,    Sex:  "male",}_, err = toy.Model(&User{}).Debug().Insert(&user)// INSERT INTO user(created_at,updated_at,name,age,sex) VALUES(?,?,?,?,?) , args:[]interface {}{time.Time{wall:0xbe8df5112e7f07c8, ext:210013499, loc:(*time.Location)(0x141af80)}, time.Time{wall:0xbe8df5112e7f1768, ext:210017044, loc:(*time.Location)(0x141af80)}, "bigpigeon", 18, "male"}// print user format with json/* {  "ID": 1,  "CreatedAt": "2018-01-11T20:47:00.780077+08:00",  "UpdatedAt": "2018-01-11T20:47:00.780081+08:00",  "DeletedAt": null,  "Name": "bigpigeon",  "Age": 18,  "Sex": "male",  "Detail": null,  "Friends": null,  "Blog": null}*/

// save data use "REPLACE INTO" when primary key exist

users := []User{    {        ModelDefault: toyorm.ModelDefault{ID: 1},        Name:         "bigpigeon",        Age:          18,        Sex:          "male",    },    {        Name: "fatpigeon",        Age:  27,        Sex:  "male",    },}_, err = toy.Model(&User{}).Debug().Save(&user)// SELECT id,created_at FROM user WHERE id IN (?), args:[]interface {}{0x1}// REPLACE INTO user(id,created_at,updated_at,name,age,sex) VALUES(?,?,?,?,?,?) , args:[]interface {}{0x1, time.Time{wall:0x0, ext:63651278036, loc:(*time.Location)(nil)}, time.Time{wall:0xbe8dfb5511465918, ext:302600558, loc:(*time.Location)(0x141af80)}, "bigpigeon", 18, "male"}// INSERT INTO user(created_at,updated_at,name,age,sex) VALUES(?,?,?,?,?) , args:[]interface {}{time.Time{wall:0xbe8dfb551131b7d8, ext:301251230, loc:(*time.Location)(0x141af80)}, time.Time{wall:0xbe8dfb5511465918, ext:302600558, loc:(*time.Location)(0x141af80)}, "fatpigeon", 27, "male"}

update

toy.Model(&User{}).Debug().Update(&User{    Age: 4,})// UPDATE user SET updated_at=?,age=? WHERE deleted_at IS NULL, args:[]interface {}{time.Time{wall:0xbe8df4eb81b6c050, ext:233425327, loc:(*time.Location)(0x141af80)}, 4}

find

find one

var user User_, err = toy.Model(&User{}).Debug().Find(&user}// SELECT id,created_at,updated_at,deleted_at,name,age,sex FROM user WHERE deleted_at IS NULL LIMIT 1, args:[]interface {}(nil)// print user format with json/* {  "ID": 1,  "CreatedAt": "2018-01-11T12:47:01Z",  "UpdatedAt": "2018-01-11T12:47:01Z",  "DeletedAt": null,  "Name": "bigpigeon",  "Age": 4,  "Sex": "male",  "Detail": null,  "Friends": null,  "Blog": null}*/

find multiple

var users []User_, err = brick.Debug().Find(&users)fmt.Printf("find users %s\n", JsonEncode(&users))// SELECT id,created_at,updated_at,deleted_at,name,age,sex FROM user WHERE deleted_at IS NULL, args:[]interface {}(nil)

delete

delete with primary key

_, err = brick.Debug().Delete(&user)// UPDATE user SET deleted_at=? WHERE id IN (?), args:[]interface {}{(*time.Time)(0xc4200f0520), 0x1}

delete with condition

_, err = brick.Debug().Where(toyorm.ExprEqual, Offsetof(User{}.Name), "bigpigeon").DeleteWithConditions()// UPDATE user SET deleted_at=? WHERE name = ?, args:[]interface {}{(*time.Time)(0xc4200dbfa0), "bigpigeon"}

ToyBrick


use toy.Model will create a ToyBrick, you need use it to build grammar and operate the database

Where condition

affective update/find/delete operation

usage

where will clean old conditions and make new one

brick.Where(<expr>, <Key>, [value])

whereGroup add multiple condition with same expr

brick.WhereGroup(<expr>, <group>)

conditions will copy conditions and clean old conditions

brick.Conditions(<toyorm.Search>)

or & and condition will use or/and to link new condition when current condition is not nil

brick.Or().Condition(<expr>, <Key>, [value])brick.Or().ConditionGroup(<expr>, <group>)brick.And().Condition(<expr>, <Key>, [value])

or & and conditions will use or/and to link new conditions

brick.Or().Conditions(<toyorm.Search>)brick.And().Conditions(<toyorm.Search>)
SearchExpr
SearchExprto sqlexample
ExprAndANDbrick.WhereGroup(ExprAnd, Product{Name:"food one", Count: 4}) // WHERE name = "food one" AND Count = 4
ExprOrORbrick.WhereGroup(ExprOr, Product{Name:"food one", Count: 4}) // WHERE name = "food one" OR Count = "4"
ExprEqual=brick.Where(ExprEqual, OffsetOf(Product{}.Name), "food one") // WHERE name = "find one"
ExprNotEqual<>brick.Where(ExprNotEqual, OffsetOf(Product{}.Name), "food one") // WHERE name <> "find one"
ExprGreater>brick.Where(ExprGreater, OffsetOf(Product{}.Count), 3) // WHERE count > 3
ExprGreaterEqual>=brick.Where(ExprGreaterEqual, OffsetOf(Product{}.Count), 3) // WHERE count >= 3
ExprLess<brick.Where(ExprLess, OffsetOf(Product{}.Count), 3) // WHERE count < 3
ExprLessEqual<=brick.Where(ExprLessEqual, OffsetOf(Product{}.Count), 3) // WHERE count <= 3
ExprBetweenBetweenbrick.Where(ExprBetween, OffsetOf(Product{}.Count), [2]int{2,3}) // WHERE count BETWEEN 2 AND 3
ExprNotBetweenNOT Betweenbrick.Where(ExprNotBetween, OffsetOf(Product{}.Count), [2]int{2,3}) // WHERE count NOT BETWEEN 2 AND 3
ExprInINbrick.Where(ExprIn, OffsetOf(Product{}.Count), []int{1, 2, 3}) // WHERE count IN (1,2,3)
ExprNotInNOT INbrick.Where(ExprNotIn, OffsetOf(Product{}.Count), []int{1, 2, 3}) // WHERE count NOT IN (1,2,3)
ExprLikeLIKEbrick.Where(ExprLike, OffsetOf(Product{}.Name), "one") // WHERE name LIKE "one"
ExprNotLikeNOT LIKEbrick.Where(ExprNotLike, OffsetOf(Product{}.Name), "one") // WHERE name NOT LIKE "one"
ExprNullIS NULLbrick.Where(ExprNull, OffsetOf(Product{}.DeletedAt)) // WHERE DeletedAt IS NULL
ExprNotNullIS NOT NULLbrick.Where(ExprNotNull, OffsetOf(Product{}.DeletedAt)) // WHERE DeletedAt IS NOT NULL
example

single condition

brick = brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Tag), "food")or use stringbrick = brick.Where("=", Offsetof(Product{}.Tag), "food")// WHERE tag = "food"

combination condition

brick = brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Count), 2).And().    Condition(toyorm.ExprGreater, Offsetof(Product{}.Price), 3).Or().    Condition(toyorm.ExprEqual, Offsetof(Product{}.Count), 4)or use stringbrick = brick.Where("=", Offsetof(Product{}.Count), 2).And().    Condition(">", Offsetof(Product{}.Price), 3).Or().    Condition("=", Offsetof(Product{}.Count), 4)// WHERE count = 2 and price > 3 or count = 4

priority condition

brick.Where(toyorm.ExprGreater, Offsetof(Product{}.Price), 3).And().Conditions(    brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Count), 2).Or().    Condition(toyorm.ExprEqual, Offsetof(Product{}.Count), 1).Search)or use stringbrick.Where(">", Offsetof(Product{}.Price), 3).And().Conditions(    brick.Where("=", Offsetof(Product{}.Count), 2).Or().    Condition("=", Offsetof(Product{}.Count), 1).Search)// WHERE price > 3 and (count = 2 or count = 1)
brick.Conditions(    brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Count), 2).Or().        Condition(toyorm.ExprEqual, Offsetof(Product{}.Count), 1).Search,).And().Conditions(    brick.Where(toyorm.ExprEqual, Offsetof(Product{}.Price), 3).Or().        Condition(toyorm.ExprEqual, Offsetof(Product{}.Price), 4).Search,)or use stringbrick.Conditions(    brick.Where("=", Offsetof(Product{}.Count), 2).Or().        Condition("=", Offsetof(Product{}.Count), 1).Search,).And().Conditions(    brick.Where("=", Offsetof(Product{}.Price), 3).Or().        Condition("=", Offsetof(Product{}.Price), 4).Search,)// WHERE (count = ? OR count = ?) AND (price = ? OR price = ?)

limit & offset

brick := brick.Offset(2).Limit(2)// LIMIT 2 OFFSET 2

order by

brick = brick.OrderBy(Offsetof(Product{}.Name))// ORDER BY name

order by desc

brick = brick.OrderBy(brick.ToDesc(Offsetof(Product{}.Name)))// ORDER BY name DESC

Template Field

sometimes the condition of sql is not a normal field, use TempField to wrapper normal field

brick = brick.Where("=", brick.TempField(Offsetof(Product{}.Name), "LOWER(%s)"), "name")// WHERE LOWER(name) = ?

Transaction


start a transaction

brick = brick.Begin()

rollback all sql action

err = brick.Rollback()

commit all sql action

err = brick.Commit()

Debug

if Set debug all sql action will have log

brick = brick.Debug()

IgnoreMode

when I Update or Search with struct that have some zero value, did I update it ?

use IgnoreMode to differentiate what zero value should update

brick = brick.IgnoreMode(toyorm.Mode("Update"), toyorm.IgnoreZero ^ toyorm.IgnoreZeroLen)// ignore all zeor value but excloud zero len slice// now field = []int(nil) will ignore when update// but field = []int{} will update when update// now field = map[int]int(nil) will ignore when update// but field = map[int]int{} will update when update

In default

OperationModeaffect
InsertIgnoreNobrick.Insert()
ReplaceIgnoreNobrick.Replace()
ConditionIgnoreZerobrick.WhereGroup(ExprAnd/ExprOr, )
UpdateIgnoreZerobrick.Update()

All of IgnoreMode

modeeffective
IgnoreFalseignore field type is bool and value is false
IgnoreZeroIntignore field type is int/uint/uintptr(incloud their 16,32,64 bit type) and value is 0
IgnoreZeroFloatignore field type is float32/float64 and value is 0.0
IgnoreZeroComplexignore field type is complex64/complex128 and value is 0 + 0i
IgnoreNilStringignore field type is string and value is ""
IgnoreNilPointignore field type is point/map/slice and value is nil
IgnoreZeroLenignore field type is map/array/slice and len = 0
IgnoreNullStructignore field type is struct and value is zero value struct e.g type A struct{A string,B int}, A{"", 0} will be ignore
IgnoreNilignore with IgnoreNilPoint and IgnoreZeroLen
IgnoreZeroignore all of the above

BindFields

if bind a not null fields, the IgnoreMode will failure

{    var p Product    result, err := brick.BindDefaultFields(Offsetof(p.Price), Offsetof(p.UpdatedAt)).Update(&Product{        Price: 0,    })   // process error   ...}var products []Productresult, err = brick.Find(&products)// process error...for _, p := range products {    fmt.Printf("product name %s, price %v\n", p.Name, p.Price)}

Scope

use scope to do some custom operation

// desc all order by fieldsbrick.Scope(func(t *ToyBrick) *ToyBrick{    newOrderBy := make([]*ModelFields, len(t.orderB 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap