Set模式应对查询业务

61 阅读2分钟

我们先介绍一下repository层User的两种形态:

第一种是以domain.User为参数的增删改查操作

Find    
FindOne   
FindMany 
Save 
Modify 
Remove

Set模式如何使用呢?以查询举例,通过属性对象的IsPresent函数来决定是否使用该属性,如下:

func (repo *User) query(db *ent.Client, qryUser domain.User) *ent.UserQuery {
    builder := db.User.Query()
    qryUser.ID.IsPresent(func(v int64) { builder.Where(user.ID(v)) })
    qryUser.Mobile.IsPresent(func(v string) { builder.Where(user.Mobile(v)) })
    qryUser.Age.IsPresent(func(v int64) { builder.Where(user.Age(v)) })
    qryUser.Level.IsPresent(func(v int64) { builder.Where(user.Level(v)) })
    qryUser.Nickname.IsPresent(func(v string) { builder.Where(user.Nickname(v)) })
    return builder
}

Set模式也完美的解决了增量更新问题,如下:

func (repo *User) modify(ctx context.Context, db *ent.Client, cmdUser domain.User) int {
    builder := db.User.Update()
    cmdUser.Mobile.IsPresent(func(v string) { builder.SetMobile(v) })
    cmdUser.Age.IsPresent(func(v int64) { builder.SetAge(v) })
    cmdUser.Level.IsPresent(func(v int64) { builder.SetLevel(v) })
    cmdUser.Nickname.IsPresent(func(v string) { builder.SetNickname(v) })
    return builder.Where(user.ID(cmdUser.ID.Value)).SaveX(ctx)
}

第二种是以依赖倒置方式的增删改查操作

Fetch 
FetchOne 
FetchMany 
Create 
Update  
Delete
Count  
Exist 
NotExist

开发中我们应该都见过这样的代码:

FindByID
FindByName
FindByMobile
FindByNameAndMobile
...

依赖倒置可以更加灵活的应对查询的各种操作,请读者自行体会。

为什么每个函数都有对应的私有函数,比如FetchOne对应私有函数fetchOne?
私有函数主要是给事务调用。

转存失败,建议直接上传图片文件

开发者都应该见到类似复杂的查询业务,常见于后台管理,商品购买查询等等,这里面包含:
1、等值查询 比如ID、手机号
2、范围查询 比如时间、年龄
3、多值查询 比如等级、状态
4、模糊查询 比如用户名、昵称

对接以上查询业务代码如下,请读者结合示例自行体会。

type UserMany struct {
    Mobile   vo.Mobile     `binding:"omitempty"`
    StartAge user.Age      `binding:"omitempty"`
    EndAge   user.Age      `binding:"omitempty"`
    Levels   user.Levels   `binding:"omitempty,dive"`
    Nickname user.Nickname `binding:"omitempty"`
}

项目结构介绍:
使用了Ent数据库框架

request层:接受外部数据
response层:对外输出数据
repository层:仓储层,负责与数据源交互,包括数据库、缓存、Api
ent层:数据库实体
domain层:领域实体

Mapper转换原则:谁有数据谁负责转换
ent.User有数据,ent.User.Mapper函数负责把自身转换为domain.User
domain.User有数据,domain.User.Mapper函数负责把自身转换为response.User

源码链接