package
1.28.2
Repository: https://github.com/webx-top/db.git
Documentation: pkg.go.dev

# README

factory

为了方便使用,将原包中的常用功能进行再次封装。支持的目标功能有:

  1. 支持主从式读写分离,支持多主多从
  2. 支持同时使用多种数据库且每一种数据库都支持读写分离
  3. 支持缓存数据结果
  4. 便捷的分页查询功能
  5. 更加的易于使用

以上。

用法

package main
import (
	"fmt"
	"log"

	"github.com/webx-top/db"
	"github.com/webx-top/db/lib/factory"
	"github.com/webx-top/db/mysql"
)

var settings = mysql.ConnectionURL{
	Host:     "localhost",
	Database: "blog",
	User:     "root",
	Password: "root",
}

type Post struct {
    Id      int     `db:"id,omitempty"`
	UserId  int     `db:"user_id"`
    Title   string  `db:"title"`
    Group   string  `db:"group"`
    Views   int     `db:"views"`
}

type PostCollection struct {
	Post *Post `db:",inline"`
	User *User `db:",inline"`
}

type User struct {
    Id      int     `db:"id,omitempty"`
    Name   string   `db:"name"`
}

func main() {
	database, err := mysql.Open(settings)
	if err != nil {
		log.Fatal(err)
	}
	factory.AddDB(database).Cluster(0).SetPrefix(`webx_`)
	factory.SetDebug(true)
	defer factory.Default().CloseAll()

	var posts []*Post

    err = factory.All(factory.NewParam().SetCollection(`post`).SetPage(1).SetSize(10).SetRecv(&posts))
	// 生成SQL:SELECT * FROM `webx_post` LIMIT 10

	if err != nil {
		log.Fatal(err)
	}

	for _, post := range posts {
		log.Printf("%q (ID: %d)\n", post.Title, post.Id)
	}
}

查询多行数据 (使用All方法)

方法 1.

err = factory.All(factory.NewParam().SetCollection(`post`).SetRecv(&posts))

也可以附加更多条件(后面介绍的所有方法均支持这种方式):

 err = factory.NewParam().SetCollection(`post`).SetRecv(&posts).SetArgs(db.Cond{`title LIKE`:`%test%`}).SetMiddleware(func(r db.Result)db.Result{
     return r.OrderBy(`-id`).Group(`group`)
 }).All()
 // 生成SQL:SELECT * FROM `webx_post` WHERE (`title` LIKE "%test%") GROUP BY `group` ORDER BY `id` DESC
 // OrderBy(`-id`) 表示按字段id的值进行降序排列,如果没有前面的负号“-”则按照升序排列

方法 2.

err = factory.NewParam().SetCollection(`post`).SetRecv(&posts).All()

方法 3.

post := &Post{}
res := factory.NewParam().SetCollection(`post`).Result()
//defer res.Close() //操作结束后别忘了执行关闭操作
for res.Next(post) {
	log.Printf("%q (ID: %d)\n", post.Title, post.Id)
}
res.Close() //操作结束后别忘了执行关闭操作

关联查询

手动 Join 查询

m := []*PostCollection{}
err = factory.NewParam().SetCollection(`post`,`a`).SetCols(db.Raw(`a.*`)).AddJoin(`LEFT`, `user`, `b`, `b.id=a.user_id`).Select().All(&m)

自动关联查询

type PostWithUser struct {
	*Post
	User *User `db:"-,relation=id:user_id"`
}
m := []*PostWithUser{}
err = factory.NewParam().SetCollection(`post`).Select().All(&m)

自动关联查询是通过在结构体 Tag 属性的 db 属性中定义 relation 参数来实现。
其完整的格式如下:

relation=User表列名:Post表列名|Post表管道函数1|Post表管道函数2,table=User表名称,dbconn=查询User表采用的数据库连接名称,columns=User中的列1&User中的列2,where=User中的列1:User中的列1值&User中的列2:User中的列2值,orderby=User中的列1&User中的列2

其中,relation=User表列名:Post表列名 是必需的,其余的为可选项。

各个参数的详细说明
  • table: 指定表名称(在无法通过左侧的字段名自动推导出表名称的情况下使用)
  • dbconn: 指定查询数据库采用的连接名称(不指定的情况下采用默认连接)
  • columns: 指定要查询的列(默认为查询所有列)。如果左侧的User字段的数据类型为 map[string]interface{} 或者 echo.H , 还需要分别对每一个字段指明数据类型,例如:columns=col1:string&col2:int , 要注意的是仅支持指定 github.com/webx-top/echo/param 包中 AsType() 函数支持的数据类型
  • where: 指定附加条件,条件的列名称和列值用冒号间隔“:”。多个条件之间用“&”分隔。列的值支持采用urlencode的结果值(按照格式urldecode(编码后的值)来设置),列值如果包含前缀~则作为原始sql语句(不会经过任何编码处理)
  • orderby: 指定排序方式。多个字段之间用“&”分隔。支持采用urlencode的结果值(按照格式urldecode(编码后的值)来设置),如果包含前缀~则作为原始sql语句
  • offset: 指定偏移值(小于或等于0的值会忽略)
  • limit: 指定查询数量(小于或等于0的值会忽略)
  • groupby: 指定 group by。多个字段之间用“&”分隔。支持采用urlencode的结果值(按照格式urldecode(编码后的值)来设置),如果包含前缀~则作为原始sql语句
内置管道函数

管道函数用于定义关联查询前需要对关联值进行预先处理的逻辑。如果管道函数返回 nil 值,则取消关联查询,这可以用来自定义判断和控制是否关联查询。

  • neq: 不等于。用法:neq(col:100) // 即Post表中的列col不等于100的时候才进行关联查询
  • eq: 等于。用法:eq(col:100) // 即Post表中的列col等于100的时候才进行关联查询
  • split: 拆分为切片。用法:split // 即Post表中的关联列的值用 strings.Split(value,",") 拆分成切片后再用 IN 查询
  • gtZero: 大于0。用法:gtZero // 即Post表中的关联列的值大于0时才进行关联查询
  • notEmpty: 非空字符串。用法:notEmpty // 即Post表中的关联列的值不为空字符串时才进行关联查询
注册自定义管道函数:
import (
	"github.com/webx-top/db/lib/sqlbuilder"
)

func init(){
	// 方式1:直接注册管道函数
	// 生成管道函数 myPipe
	sqlbuilder.PipeList.Add("myPipe",func(row reflect.Value, val interface{}) interface{}{
		// 你的代码
		return val
	})

	// 方式2:注册管道函数生成器
	// 生成管道函数 myPipeGenerator(params)
	sqlbuilder.PipeGeneratorList.Add("myPipeGenerator",func(params string) sqlbuilder.Pipe {
		// 你的代码
		return func(row reflect.Value, v interface{}) interface{} {
			// 你的代码
			return v
		}
	})
}

查询分页数据 (使用List方法)

方法 1.

var countFn func()int64
countFn, err = factory.List(factory.NewParam().SetCollection(`post`).SetRecv(&posts).SetPage(1).SetSize(10))

方法 2.

countFn, err = factory.NewParam().SetCollection(`post`).SetRecv(&posts).SetPage(1).SetSize(10).List()

查询一行数据 (使用One方法)

方法 1.

var post Post
err = factory.One(factory.NewParam().SetCollection(`post`).SetRecv(&post))

方法 2.

var post Post
err = factory.NewParam().SetCollection(`post`).SetRecv(&post).One()

插入数据 (使用Insert方法)

方法 1.

var post Post
post=Post{
    Title:`test title`,
}
err = factory.Insert(factory.NewParam().SetCollection(`post`).SetSend(&post))

方法 2.

var post Post
post=Post{
    Title:`test title`,
}
err = factory.NewParam().SetCollection(`post`).SetSend(&post).Insert()

更新数据 (使用Update方法)

方法 1.

var post Post
post=Post{
    Title:`test title`,
}
err = factory.Update(factory.NewParam().SetCollection(`post`).SetSend(&post).SetArgs("id",1))

方法 2.

var post Post
post=Post{
    Title:`test title`,
}
err = factory.NewParam().SetCollection(`post`).SetSend(&post).SetArgs("id",1).Update()

删除数据 (使用Delete方法)

方法 1.

err = factory.Delete(factory.NewParam().SetCollection(`post`).SetArgs("id",1))

方法 2.

err = factory.NewParam().SetCollection(`post`).SetArgs("id",1).Update()

使用事务

方法 1.

param = factory.NewParam().SetCollection(`post`).SetTxMW(func(t *factory.Transaction) (err error) {
	param := factory.NewParam().SetCollection(`post`).SetSend(map[string]int{
		"views": 1,
	}).SetArgs("id", 1)
	err = t.Update(param)
	// err=fmt.Errorf(`failured`)
	// 当返回 nil 时,自动执行Commit,否则自动执行Rollback
	return
})
factory.Tx(param)

方法 2.

param = factory.NewParam().Begin().SetCollection(`post`)
err:=param.SetSend(map[string]int{"views": 1}).SetArgs("id", 1).Update()
if err!=nil {
    param.End(err)
    return
}
err=factory.NewParam().TransFrom(param).SetCollection(`post`).SetSend(map[string]int{"views": 2}).SetArgs("id", 1).Update()
if err!=nil {
    param.End(err)
    return
}
err=factory.NewParam().TransFrom(param).SetCollection(`post`).SetSend(map[string]int{"views": 3}).SetArgs("id", 1).Update()
param.End(err)

自动生成数据表的结构体(struct)

进入目录github.com/webx-top/db/cmd/dbgenerator执行命令

go build -o dbgenerator.exe
dbgenerator.exe -u <数据库用户名> -p <数据库密码> -h <数据库主机名> -e <数据库类型> -d <数据库名> -o <文件保存目录> -pre <数据表前缀> -pkg <生成的包名>

支持的参数:

  • -u <数据库用户名> 默认为root

  • -p <数据库密码> 默认为空

  • -h <数据库主机名> 默认为localhost

  • -e <数据库类型> 默认为mysql

  • -d <数据库名> 默认为blog

  • -o <文件保存目录> 默认为dbschema

  • -pre <数据表前缀> 默认为空

  • -pkg <生成的包名> 默认为dbschema

  • -autoTime <自动生成时间戳的字段> 默认为update(*:updated)/insert(*:created)

    即在更新任意数据表时,自动设置表的updated字段; 在新增数据到任意数据表时,自动设置表的created字段。
    括号内的格式:<表1>:<字段1>,<字段2>,<...字段N>;<表2>:<字段1>,<字段2>,<...字段N>

本命令会自动生成各个表的结构体和所有表的相关信息

生成的文件范例:blog结构体文件

每一个生成的结构体中都自带了以下常用方法便于我们使用:

  • 获取事务 Trans() *factory.Transaction
  • 设置事务 Use(trans *factory.Transaction) factory.Model
  • 新参数对象 NewParam() *factory.Param
  • 设置默认参数对象 SetParam(param *factory.Param) factory.Model
  • 获取参数对象 Param() *factory.Param (如果有默认参数对象则使用默认,否则新建参数对象)
  • 复制列表数据结果集 Objects() []*结构体名
  • 新建列表数据结果集 NewObjects() *[]*结构体名
  • 查询一行 Get(mw func(db.Result) db.Result, args ...interface{}) error
  • 分页查询 List(recv interface{}, mw func(db.Result) db.Result, page, size int, args ...interface{}) (func() int64, error)
  • 根据偏移量查询 ListByOffset(recv interface{}, mw func(db.Result) db.Result, offset, size int, args ...interface{}) (func() int64, error)
  • 添加数据 Insert() (interface{}, error)
  • 修改数据 Update(mw func(db.Result) db.Result, args ...interface{}) error
  • 删除数据 Delete(mw func(db.Result) db.Result, args ...interface{}) error
  • 统计行数 Count(mw func(db.Result) db.Result, args ...interface{}) error

如果数据库中的字段含有注释,并且注释内容是以反引号`...`这样的样式开头,
那么反引号内的内容会作为是否在该表结构体字段上的db标签添加omitemptypk的依据。
例如:数据表user的字段username注释为`omitempty`用户名,则该结构体就会生成这样:

...
type User struct {
	Username string `db:"username,omitempty" bson:"username,omitempty" comment:"用户名" json:"username" xml:"username"`
}

又例如:数据表user的字段username注释为`omitempty,pk`用户名,则该结构体就会生成这样:

...
type User struct {
	Username string `db:"username,omitempty,pk" bson:"username,omitempty,pk" comment:"用户名" json:"username" xml:"username"`
}

我们还可以根据生成的数据表信息来验证表或字段的类型和合法性,比如:

  • 验证表是否存在 factory.ValidTable(tableName)
  • 验证表中的字段是否存在 factory.ValidField(tableName,fieldName)
  • 获取某个表中某个字段的信息 factory.Fields[tableName][fieldName]

# Packages

No description provided by the author
No description provided by the author

# Functions

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
BatchValidate 批量验证值是否符合数据库要求.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Exec execute SQL.
ExistField 字段是否存在(表名不带前缀).
No description provided by the author
ExistTable 表是否存在(表名不带前缀).
FieldFind 获取字段信息(表名不带前缀).
FieldRegister 注册字段信息(表名不带前缀).
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
MathGCD 最大公约数.
MathNGCD n个数的最大公约数.
ModelRegister 模型构造函数登记.
No description provided by the author
No description provided by the author
No description provided by the author
NewCluster : database cluster.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
NewModel 模型实例化.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Query query SQL.
QueryRow query SQL.
QueryTo query SQL.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
TableNamerGet 获取表名称生成器(表名不带前缀).
TableNamerRegister 注册表名称生成器(表名不带前缀).
ToCamleCase : webx_top => WebxTop.
ToSnakeCase : WebxTop => webx_top.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
Validate 验证值是否符合数据库要求.
No description provided by the author

# Constants

DefaultDBKey 默认数据库标识.
创建后.
创建前.
删除后 (!!! 特别注意:删除之后将无法再获取此model数据).
删除前.
读取后.
读取前.
更新后.
更新前.
webx_top => webxTop.
webx_top => WebxTop.
WebxTop => webx_top.

# Variables

AllAfterReadEvents 所有读事件.
AllAfterWriteEvents 所有写事件.
No description provided by the author
No description provided by the author
DefaultDBI default.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
DefaultTableNamer default.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author
Cluster : database cluster.
No description provided by the author
DBI 数据库信息.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
FieldInfo 字段信息.
No description provided by the author
No description provided by the author
No description provided by the author
ModelInstancer 模型实例化.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Interfaces

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Type aliases

No description provided by the author
No description provided by the author
No description provided by the author
FieldValidator 字段验证器.
No description provided by the author
ModelInstancers 模型实例化.
No description provided by the author
No description provided by the author