前言
在日常工作当中开发人员接触的最多的非数据库莫属了,那么就需要一套统一数据库工具类,不管使用什么样的语言,一致的接口定义可以大大简化开发人员的学习成本,也能更容易整合框架.
虽然此篇文章是面向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
}
结尾
那么今天就到这里了,如果文章中有任何错误或者疑问欢迎提问,我会尽快回复的,如果文章对你有帮助也欢迎打赏,谢谢.