Repository 层的代码如何封装才比较合适?

2021-05-28 12:09:22 +08:00
 waibunleung

有两个 case,分别是不同人封装的,下面是伪代码:

case1:

// 根据用户昵称获取用户信息
function findUserByName(name){
    // 获取数据库链接
    db = _get_db()
    if (not db){
    	return error
    }

	// orm 查询
    user, err = db.where('name', name).get(table_name)
    if (err) {
        LOG("查找姓名失败", err)
        return error
    }

    return user
}

// 根据用户 ID 获取用户信息
function findUserById(userid){
    // 获取数据库链接
    db = _get_db()
    if (not db){
    	return error
    }

	// orm 查询
    user, err = db.where('id', userid).get(table_name)
    if (err) {
        LOG("查找用户 id 失败", err)
        return error
    }

    return user
}

// service 层调用
user1 = userRepo.findUserByName('拜拜你条尾')
user2 = userRepo.findUserById(12)
code ...

case2:

// 简单封装了查询函数?
function query(where_array, limit){
    // 获取数据库链接
    db = _get_db()
    if (not db){
    	return error
    }
	
    // orm 查询
    user, err = db.where(where_array).limit(limit).get(table_name)
    if (err) {
        LOG("查找用户失败", err)
        return error
    }

    return user
}

// service 层调用
user1 = userRepo.query({name = '拜拜你条尾'}, 1)
user2 = userRepo.query({id = 12}, 1)
code ...

case2 这种封装有点迷的感觉,不能 cover 大部分的情况(where in/ or 之类),那这样的封装的意义何在?倒不如像第一种一样,不同的查询条件就封装一个方法,见名知意,不会给人带来疑惑?

不知道各位怎么看...

另外像请教下大家在这一层是怎么封装代码的?

3355 次点击
所在节点    程序员
32 条回复
waibunleung
2021-05-28 14:22:15 +08:00
太惨了....是没有人明白我在说什么吗....
juzzle
2021-05-28 14:35:11 +08:00
仓储层应该是组合数据吧,sql 语句你应该放到 model 层吧
gongym
2021-05-28 14:46:38 +08:00
这个应该都是生成的吧,自动生成 get 的方法和 query 方法。query 方法就是传入参数自动解析拼接成查询条件,这个就看封装能力了,一般的查询 like,eq,in 等还有排序条件等简单封装一下就够了吧。其余的情况就在生成代码的基础上自己写单独的方法实现
gongym
2021-05-28 14:55:54 +08:00
解析查询条件,简单点如果实体类和数据库字段对应规则可以确定的话,传入实体类范型,遍历字段和值,就可以完成 eq 条件查询了。如果不好对应就传入 map,key 是字段+查询情况( like,eq,ne,gt,lt 等) value 就是值。这样就完成了查询条件的拼接了
gongym
2021-05-28 14:57:39 +08:00
可以参考下 mybatis 生成的 example 和 criteria 。我感觉这个思路还是很强大的。就是太复杂了。我们用不到那么复杂后期就换 mybatis plus 了
simonlu9
2021-05-28 14:59:06 +08:00
参考下 jpa 吧,方便得一批
waibunleung
2021-05-28 15:36:37 +08:00
这不是 java 的那一套....
应该说是语言无关的 php,go python 之类的都可以这么写
@simonlu9
@gongym
waibunleung
2021-05-28 15:37:00 +08:00
@gongym case2 不是自动生成的,是人写的
ksc010
2021-05-28 15:58:13 +08:00
case2 更灵活一些 我的理解 目的就是为了减少代码量
InvincibleDream
2021-05-28 16:06:45 +08:00
case2 改个名呗 query_with_limits 设置为私有,然后再写俩个 wrapper 一个 findUserByName 一个 findUserById 。这样两个方法的实现比较好维护。
meshell
2021-05-28 16:08:38 +08:00
工资按代码量选 1 反之 2//doge
BeautifulSoap
2021-05-28 16:09:12 +08:00
让我选,那应该是 case1 吧,case2 的想法其实是可以的,但写法有问题

case2 这写法泄露了数据结构。`user1 = userRepo.query({name = '拜拜你条尾'}, 1)` 中的 `name` 是具体 BD 的字段名 ,repository 目的之一不就是隔离具体的数据存储过程吗。这样写的话,意味着具体数据的结构溢出到了其他的领域层(比如调用 repo 的是 Service 层)

case2 改改的话 `query(id int, name string, limit int)` 自动根据 id 和 name 哪个是空值自动创建 sql,或者动态语言的话直接 定义`query(user_info)` ,根据 user_info 的的类型( int 或 string )来创建对应的 sql (虽说感觉后者的方法可能今后不太好维护)
devld
2021-05-28 16:11:08 +08:00
我理解的是,repository 层就不要向上层暴露细节了(比如 where 条件)。
#10 的就挺好的
thtznet
2021-05-28 16:24:48 +08:00
用 EF, 注入 context 。啊? java ?算了算了,手写吧。
waibunleung
2021-05-28 16:24:59 +08:00
@ksc010 灵活只是相对的,case2 的做法只是能让人方便添加 where and 的条件,但是要兼容 where in 或者 where or 的时候要怎么办呢?而且取了个叫 query()的名字,看上去就比较兼容多种查询情况的样子....实际上又不是能做大部分的工作。
如果我有一个 where in 的查询,那我是不是要重新封装一个函数?那这个时候这个函数叫什么好?
waibunleung
2021-05-28 16:25:14 +08:00
@thtznet 动态语言
xiaoyiqingz
2021-05-28 16:40:42 +08:00
Repository 感觉应该隐藏掉数据的存储方式吧,比如数据会存储在不同的位置,不同类型数据库,甚至是在文件里,对外只提供获取数据的接口。也有可能需要获取的数据并不对应一个数据表,可以在 Repository 做一些处理,所以 findUserByName 这种表意且隐藏数据存储方式的感觉会更好一些。userRepo.query 这种方式感觉就是要操作数据库了
mcfog
2021-05-28 16:47:45 +08:00
1 是 repository 2 是 database helper
做成 1 调用 2 都行
waibunleung
2021-05-28 17:26:42 +08:00
@mcfog 有 orm 的链式调用的,如果说要做成 1 再调用 2,那为什么不直接用 orm db.where(‘name’, name).get()

而是
function getUserByName(name){
return self.query({‘name’ = name})
}
waibunleung
2021-05-28 17:26:55 +08:00
@devld 有 orm 的链式调用的,如果说要做成 1 再调用 2,那为什么不直接用 orm db.where(‘name’, name).get()

而是
function getUserByName(name){
return self.query({‘name’ = name})
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/779785

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX