WEB应用的业务逻辑,基本都在model层,但我习惯将model层分成 Service和Dao的两层结构。本篇主要讲述框架中Dao及Service的实现及使用,重点是MySQL常用操作的封装。
数据模型分层
-
DAO
即数据访问对象,在我的框架中,定义为直接对指定的“某个数据源”的增删改查的封装。
对于简单常用的增删改查,开发者可以直接使用框架的Dao对象来操作。
对于较为复杂的操作,比如复杂的条件语句,连表等,也保留执行手写SQL语句的功能。
-
Service
service层主要是封装较为复杂的业务逻辑,包括事务封装。
一般地,service基于dao进行封装,目的是将一个需要多次数据交互来完成的完整操作进行整合。 比如读取用户todo任务列表的逻辑:
-
先从 memcache中读取缓存,如有,直接返回
-
缓存没有,从数据库中读取,读取成功后保存到缓存并返回
-
也可以在service层封装与dao操作无关的业务逻辑。比如 然后发送网络请求和请求结果的加工。
Dao实现
根椐协议方式,对数据源的访问,通常是分为SQL语句类和GET/SET类,前者代表是关系数据库,后者的代表是memcache。我的框架也是优先实现了MySQL和Memcache的Dao,而对于目前比较火的redis和mongodb因为本人用得比较少,就暂不支持。
memcache dao
对于memcache的访问,github.com/bradfitz/gomemcache/ 已支持的很好了,唯一不习惯的是 方法传递和返回的参数是items结构,我又手多的按php的使用习惯,在gomemcache的基础上做了个wrapper:
-
将Get/GetMulti的返回类型改成了[]byte,可以直接使用。
-
对于Add/Set/Replace方法,则将单个参数的item结构分拆为多个参数
原来是这个样子的:
//add
item := &memcache.Item{Key: key, Value: data, Expiration: expire}
Client.Add(item)
//get
item, _ := Client.Get(key)
value:= item.Value
我改成了这样:
func(this *Mc) Add(key string, data []byte, s ...int32){}
func (this *Mc) Get(key string) ([]byte, error) {}
题外:
php用多了,还是挺喜欢在函数定义中使用默认参数的,所以在go里,就有很多 ...xxx类型的参数,比如在Add时,不指定第三参数的话,会有一个默认的expire
mc的协议是比较简单的基于文本的协议,有兴趣的也可以完全自己实现MC的整个操作。
mysql dao
核心需求
对mysql的操作,我选择了基于github.com/go-