关于dao层的设计与思考

dao层简介

dao-Data Access Objects又叫做数据访问对象,主要是做数据持久层的工作,简单点来说就是负责对数据进行增删改查。一般来说实现dao之前需要定义dao的接口,然后实现接口。在实际开发中,一般来讲一个model对应一个dao。例如存在user代表用户信息,用户信息保存在数据库中,为了对用户信息进行一些操作需要实现userDao,来完成对用户信息的增删改查操作。

如何设计dao层

在实际的需求中,假设有如下需求,以mysql的查询为例,某个表中存在A,B,C,D四个字段,某些情况下需要根据A字段来进行查询,某些情况下需要根据A, C字段查询等等,总是就是根据业务需求的不同,会对应不同的过滤条件。那么这时我们应该如何实现dao层呢?据本人所了解有三种比较常见的方法,具体如下:


1. 根据查询字段的不同实现不同的查询方法。例如根据A字段查询可以实现一个GetXXXByA的方法,根据A和C字段查询可以实现一个GetXXXByAAndC方法等等······ 细心的小伙伴可能会发现对于每一种新的查询条件都需要取在dao层实现一个对应的方法,这里总结下我个人认为该种实现方法的优缺点。

优点:根据方法名可以直观的看出查询条件,有比较明确的语义。

缺点:1. 基本不可以复用。2. 根据查询条件的不同需要实现不同的方法,若不同的查询组合条件非常多,dao层会变的很重。


2. 将不同的查询条件赋值到一个dto中,仅实现一个查询方法即可,然后在查询方法中根据dto中字段不同的值来判断是否需要进行过滤,即根据字段的值来拼接where条件,最终交给db去处理,可以简单的理解为这里说到的dto就是自己定义的查询协议,外部需要根据查询协议传入特定的字段进行查询,接下来举一个具体的例子。我们来定义如下dto(使用的是golang语言):

type QueryConditionDto struct {
	A       int32  // A=-1不对A进行等值过滤,A>=0需要在where中加入A = xx
	B       string // 同上面的A
	StartTs uint64 // =0不过滤时间,当>0时,需在where中加入createTime >= xxx
	EndTs   uint64 // =0不过滤时间,当>0时,需在where中加入createTime < xxx
}

上面的dto除了ts是范围过滤,其它字段的过滤均是等值过滤,并且均是and条件,不存在or条件。有细心的小伙伴看到这里可能已经发现了会存在的一些问题,接下来总结下我认为这种方法的优缺点。

优点:可复用性比较强,对于某些查询条件,可以提取出公共的特征,将条件信息输入到dto中,一个dto对应一个查询方法即可,在方法中根据dto来拼接过滤项,例如某些sql查询条件仅存在and条件,并且除了ts均是等值查询。

缺点:1. 对于不同特征的查询需要封装成不同的dto,若特征太多的话会存在很多dto查询条件对象,对于后续新增的查询条件可能没办法直观的对dto对象进行选择;2. 语义不明确,从dto对象中没办法直观的看出查询条件,从函数名称中可能也无法看出具体的含义,需要对比代码中的注释一一比对才能得知具体的查询条件。


3. 最后一种方法其实和第二种方法有点类似,使用第二种方法定义的dto仅可对A进行等值过滤,并且where中条件的连接必须是and,第三种方法实现了更为复杂的封装,例如可以通过某个字段来决定A的比对条件,可能是=比对,也可以是!=比对,也有可能是模糊比对%xxx%等等···并且where间的条件可以是灵活变动的,可以是and或者是or,通过更进一步封装也可实现 where (A or B) and (C or D)·····这里就不给出具体的实现例子啦·····

优点: 通过更为复杂的封装基本可以解决一切可能出现的查询条件,复用性非常高,通过该种手段有可能只需实现一种查询方法即可。

缺点:1. 语义不明确,和方法2一样,也没办法直观的看出查询条件。2. 对查询条件的构造成本会很大,例如仅仅需要判断where A = x,却需要构造一个很复杂的查询结构。

实际开发中的建议

上面介绍的3种dao层的设计想必大家都已经了解各自的优点及缺点了,那么我们在实际的开发过程中,应该用哪种设计比较合适呢?此处仅代表我个人的建议哈,个人在实际开发过程中是绝对不会使用第3种设计的,因为对于业务来讲,查询条件一般还是比较简单的,所以没必要做那么重的封装。1和2的话我个人会针对业务场景进行混合使用,毕竟1和2各有千秋并且相对来讲比较轻量级,如果想通过2提高复用性,个人建议对于经常使用的查询特征进行封装即可。其实and + 等值查询 + 时间范围过滤基本是比较常用的查询了。对于不太常用的查询条件,例如or,或者模糊匹配,或者!=查询使用1即可。其次再使用2的过程中最好在调用dao层的地方加一些必要注释,让他人能直观的看出查询条件具体过滤项。

你可能感兴趣的:(其它,后端)