前言

在日常工作当中开发人员接触的最多的非数据库莫属了,那么就需要一套统一数据库工具类,不管使用什么样的语言,一致的接口定义可以大大简化开发人员的学习成本,也能更容易整合框架.

虽然此篇文章是面向go的数据库工具类,但是接口定义仍然会与《C# - SQLite工具类》一致而且实现方式也类似,无非就是用go语言实现而已,使用的库为github.com/jmoiron/sqlx,该库已经支持?参数,因此实现起来更加方便.

文章中主键依然固定为ID且类型为string.其余的大家可以自行扩展.

文章中使用另外一个库为: https://github.com/ahl5esoft/golang-underscore, 该库提供了类似C# Linq的功能.

接口

首先来看一下go内的接口定义,代码如下:

type IFactory interface {

Db(entry interface{}, uow IUnitOfWork) IRepository

Uow() IUnitOfWork

}

type IRepository interface {

Add(entry interface{}) error

Query() IQuery

Remove(entry interface{}) error

Save(entry interface{}) error

}

type IQuery interface {

Count() (int64, error)

Order(fields ...string) IQuery

OrderByDesc(fields ...string) IQuery

Skip(v int) IQuery

Take(v int) IQuery

ToArray(dst interface{}) error

Where(args ...interface{}) IQuery

}

type IUnitOfWork interface {

Commit() error

}

IUnifOfWork

type unitOfWork struct {

AddQueue []interface{}

DB *sqlx.DB

RemoveQueue []interface{}

SaveQueue []interface{}

}

func (m *unitOfWork) Commit() error {

tx := m.DB.MustBegin()

underscore.Chain(m.AddQueue).Each(func(r interface{}, _ int) {

// tx.MustExec("新增SQL", "字段1值", "字段1值", ..., "字段n值")

})

m.AddQueue = make([]interface{}, 0)

underscore.Chain(m.RemoveQueue).Each(func(r interface{}, _ int) {

// tx.MustExec("删除SQL", "主键字段值")

})

m.RemoveQueue = make([]interface{}, 0)

underscore.Chain(m.SaveQueue).Each(func(r interface{}, _ int) {

// tx.MustExec("更新SQL", "字段1值", "字段1值", ..., "主键字段值")

})

m.SaveQueue = make([]interface{}, 0)

return tx.Commit()

}

func (m *unitOfWork) RegisterAdd(entry interface{}) {

m.AddQueue = append(m.AddQueue, entry)

}

func (m *unitOfWork) RegisterRemove(entry interface{}) {

m.RemoveQueue = append(m.RemoveQueue, entry)

}

func (m *unitOfWork) RegisterSave(entry interface{}) {

m.SaveQueue = append(m.SaveQueue, entry)

}

func newUnitOfWork(sqlxDB *sqlx.DB) IUnitOfWork {

return &unitOfWork{

AddQueue: make([]interface{}, 0),

DB: sqlxDB,

RemoveQueue: make([]interface{}, 0),

SaveQueue: make([]interface{}, 0),

}

}

IQuery

type orderOption struct {

Field string

Flag string

}

type queryOption struct {

Orders []orderOption

Skip int

Take int

Where string

WhereArgs []interface{}

}

type query struct {

DB *sqlx.DB

ModelType reflect.Type

Option queryOption

}

func (m *query) Count() (count int64, err error) {

var sql string

// 略, 构建查询数量SQL

err = m.DB.Get(&count, sql, m.Option.WhereArgs...)

return

}

func (m *query) Order(fields ...string) IQuery {

return m.order("ASC", fields...)

}

func (m *query) OrderByDesc(fields ...string) IQuery {

return m.order("DESC", fields...)

}

func (m *query) Skip(v int) db.IQuery {

m.Option.Skip = v

return m

}

func (m *query) Take(v int) IQuery {

m.Option.Take = v

return m

}

func (m *query) ToArray(dst interface{}) (err error) {

var sql string

// 略, 构建查询数据SQL

err = m.DB.Select(dst, sql, m.Option.WhereArgs...)

return

}

func (m *query) Where(args ...interface{}) IQuery {

underscore.Chain(args).Each(func(r interface{}, i int) {

if i == 0 {

m.Option.Where = r.(string)

m.Option.WhereArgs = make([]interface{}, 0)

} else {

m.Option.WhereArgs = append(m.Option.WhereArgs, r)

}

})

return m

}

func (m *query) order(flag string, fields ...string) IQuery {

underscore.Chain(fields).Each(func(r string, _ int) {

m.Option.Orders = append(m.Option.Orders, orderOption{

Field: r,

Flag: flag,

})

})

return m

}

func newQuery(sqlxDB *sqlx.DB, modelType reflect.Type) IQuery {

return &query{

DB: sqlxDB,

ModelType: modelType,

Option: queryOption{

Orders: make([]orderOption, 0),

},

}

}

IRepository

type repository struct {

DB *sqlx.DB

IsTx bool

ModelType reflect.Type

Uow *unitOfWork

}

func (m repository) Add(entry interface{}) error {

if err := m.Uow.RegisterAdd(entry); err != nil || m.IsTx {

return err

}

return m.Uow.Commit()

}

func (m repository) Query() IQuery {

return newQuery(m.DB, m.ModelType)

}

func (m repository) Remove(entry interface{}) error {

if err := m.Uow.RegisterRemove(entry); err != nil || m.IsTx {

return err

}

return m.Uow.Commit()

}

func (m repository) Save(entry interface{}) error {

if err := m.Uow.RegisterSave(entry); err != nil || m.IsTx {

return err

}

return m.Uow.Commit()

}

func newRepository(sqlxDB *sqlx.DB, modelType reflect.Type, isTx bool, uow *unitOfWork) IRepository {

return &repository{

DB: sqlxDB,

IsTx: isTx,

ModelType: modelType,

Uow: uow,

}

}

IFactory

type factory struct {

DB *sqlx.DB

}

func (m factory) Db(entry interface{}, uow IUnitOfWork) IRepository {

var isTx bool

var tempUow *unitOfWork

if uow == nil {

isTx = false

tempUow = m.Uow().(*unitOfWork)

} else {

isTx = true

tempUow = uow.(*unitOfWork)

}

return newRepository(

m.DB,

reflect.TypeOf(entry),

isTx,

tempUow,

)

}

func (m factory) Uow() IUnitOfWork {

return newUnitOfWork(m.DB)

}

// New is 创建mysql IFactory

func New(connString string) (f IFactory, err error) {

var db *sqlx.DB

if db, err = sqlx.Open("mysql", connString); err != nil {

return

}

f = &factory{

DB: db,

}

return

}

结尾

那么今天就到这里了,如果文章中有任何错误或者疑问欢迎提问,我会尽快回复的,如果文章对你有帮助也欢迎打赏,谢谢.