技术解析

带着 orm 封装的疑问,我又来了~!
0
2021-06-01 13:48:07
idczone

事情是这样的,在有了 orm 之后,在封装一层数据访问层,我觉得是没有大问题的。但是问题是怎么进行封装比较合适呢? 下面是两个 case (伪代码):
case1:

// 新增用户昵称
function addName(user_id, name){
    // 获取数据库链接
    db = _get_db()
    if (not db){
    	return error
    }

    add_time = time()

    insert_row = {
        user_id = user_id,
        name = name,
        status = this.status_using,
        add_time = add_time,
        updated_time = add_time,
    }
    insert_id, err = db.add(table, insert_row)
    if (err) {
        LOG("添加姓名失败" ,insert_row ,insert_id ,err)
        return error
    }

    return true
}

// service 层调用
res = xxx.addName(12, '拜拜你条尾')

code ...

case2:

function db_option(handlearr){
    is_ok = false
    if (len(handlearr) <= 0) {
        return is_ok
    }

    db = _get_db()
    if (not db){
    	return is_ok
    }

    for (index, option in handlearr) {
        is_ok = true抗投诉服务器
        if (option.cmd== '__delete') {
            res = db.delete(option.table_name, option.data)
            if (res <= 0) {
                LOG("delete data err where:",json_encode(option.data))
                is_ok = false
            }
        }
        if (option.cmd== '__insert'){
            res = db.add(option.table_name, option.data)
            if (not res) {
                LOG("insert data failed:",json_encode(option.data))
                is_ok = false
            }
        }
    }
    return is_ok
}

// service 层调用
handlearr = [
    {cmd = '__insert',table_name = 't_user', data = userinfo},  
    {cmd = '__delete',table_name = 't_device', data = {id = deviceinfo.id}}
]

res = db_option(handlearr)

code ...

1.想知道怎样的封装才是比较合适的?个人认为第一种就够了,第二种的话好像慢慢会封装成另一个 orm 的感觉,而且隐藏的细节更多了.... 2.dao 层对 orm 再封装的话,怎么样才比较符合认知?

求各位赐教!


拥有 ORM 只需要封装查询,增、删、改不需要封装到数据访问层里面。
毕竟增、删、改这些业务逻辑比较固定且一般都是面向对象操作。但是查会根据不同的条件查询,这里面变化比较多,所以封装到数据访问层里面方便后期迭代优化。

第二种简直是格林斯潘第十定律……

没太 get 到这个点

那删除是直接在 service 层调用?但是我想问的问题不是这个,而是哪种封装更合适一点?
我觉得,像第一种的那样,我明确告诉你就是用了添加用户姓名的,不满足你的直接再封装一个,这样的界限明确。
第二种这样,半通用半不通用的风格就比较难受,你说我要扩展的时候,是直接改你的,还是直接封装个新的?而且 新增__insert 这样的映射,有了 orm 还搞一套命令映射,我有点不理解....

抛弃第二种,第一种的话跟你直接用 ORM 的对象操作也一样,只不过是分散到 services 里面。
比如
function create(name, age) {
user = new User()
user.setName(name)
user.setAge(age)
user.save()
}
function delete(id) {
user = UserDAO.findById(id)
if (!user) {
return error
}
user.delete()
}

class UserDAO {
function findById(id) {
return UserORM.find('id = %d', id);
}
}

你这例子我感觉跟第一种都是一样的,dao 本来就是一个分层收口的作用,强调一个分层,你现在 dao 类也是基于 orm 封装了一层给外面用,我只是少了 dao 这个类,直接用了 orm 而已。例如你的 delete(id)函数我就变成了:
function delete(id) {
user = UserORM.find({id = id})
if (!user) {
return error
}
user.delete()
}

我是说,你的第二种,基本就是重新实现了一个不完整的 lisp
(db-do (insert 't_user userinfo)
(delete 't_device `([id ,id])))
就目前来看,你的两个重新封装都是多余的。
1. 你的 addName 并没有明确地与 xxx 产生关系,没必要将它放在 xxx 里。
最基本的,应当至少产生硬绑定 user.addSomething(...){ db.add({user_id:user.id, ...}) } 才有必要写在 user 这里。
2. 它其实根本没有降低任何复杂性,甚至干扰了表达力弱的类型系统的静态分析工作。

https://github.com/ckpack/pg-helper
要不借鉴借鉴我之前写的,单表操作还是挺嗨的
数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服