一个基于Go 语言的数据库 ORM 设计史
后来,更新的第二版, 一个固定的webapi,用_db=DATABASENAME&_tb=TABLENAME&field=_xxx 这种方式实现数据库查询, 然后golang部分也实现了通过一个 struct 制定tag 的方式, 动态调用这个api。 到这一步, orm 其实已经很好用了, 专心设计数据库, 和专心写struct 就可以。 但问题出来了一些, api部分功能升级,牵扯到了golang库的变动, 就算尽量保持一致, 累的很难维护, 新项目时, 可能又要独立一套webapi(项目服务器完全分开)。当时设计的struct 操作方法, 也有些麻烦,比如(老方法, 于公开的版本无关):
//修改一个累的方法。
type UserInfo struct {
Uid uint32 `json:"uid" index:"pk"`
UserName string `json:"username" `
Money int `json:"money"`
}
u:=new(UserInfo)
u.Uid=1
mode:=orm.PlotCache(u)
mode.Set("UserName" , "xxxx")
mode.Save()
mode.Incy("money",+1)
mode.Save()
u = new(UserInfo)
u.Uid=0
u.UserName="xxxx"
u.Money =111
orm.Save(u) //添加
u = new(UserInfo)
u.Uid=1
u.UserName="xxxx"
u.Money =111
orm.Save(u) //修改
看似还可以。 不过每次使用时, 你的代码就必须有一个mode 的变量在跟着转悠, orm变量来回调用, 代码量大了, 会让阅读很困难。 于是, 有了现在的发布的这一版ORM .
type UserInfo struct {
orm.Object
Uid uint32 `field:"uid" index:"pk"`
UserName string `field:"string"`
Money int `json:"money"`
}
func(self *UserInfo)GetTableName()string{
return "database.tablename"
}
u:=new(UserInfo)
all,err:= u.Objects(u).All() //提取所有
all,err:= u.Objects(u).Filter("Uid__gt" , 100).All() // Uid > 100 的。
u.Objects(u).Filter("Uid__gt",100).Limit(0,10).All() //取10条记录。
param:= u.Objects(u).Filter("Uid__gt",100)
param.FilterOr("Money__lt", 500)
param.All() // Uid >100 or Money < 500的。
u:=new(UserInfo)
u.Uid=1
u.Objects(u).One() //提取一个
u.UserName="111111"
u.Money = 1000
u.Save() //保存
u.Change("Money__add" , 1) //money +1
u.Save() //保存。
u.Delete() //删除掉
这样操作起来容易很多了。 还有更多的操作符, 可以看 https://github.com/ablegao/orm/blob/master/marsharl_driver_mysql.go 里面_w 函数方法
这个版本的orm , 直接使用的sql 驱动, 不在受webapi的限制。 而扩展数据库很容易, 可以参考marsharl_driver_mysql.go 里面的内容。
上面这些,并非这个orm的重点功能。频繁的数据库修改,和一些没必要必须摄入到数据库里面的数据缓存, 是这个ORM的重点。
所以这个ORM有另外一个Redis缓存扩展:
type UserInfo struct {
orm.CacheModule //注意这里的变化
Uid uint32 `field:"uid" index:"pk" cache:"info" cache_profix:"user"`
UserName string `field:"string"`
Money int `json:"money"`
}
func(self *UserInfo)GetTableName()string{
return "database.tablename"
}
和上面的类区变化不大,更换了orm.Object 为orm.CacheModule . 增加cache tag , 和第一个字段增加 cache_profix.
很抱歉的是, 我很难保证orm.CacheModule 和orm.Object的通用性, 所以 如果要切换时, Filter方法有些字段不可用。
u:=new(UserInfo)
u.Uid=1
u.Objects(u).One()
这样, redis中会增加一个key user:1:info 内容是hash 的userInfo所有字段数据。
然后你下次在使用时:
u:=new(UserInfo)
u.Uid=1
u.Objects(u).One() //你的数据将会从Redis中提取, 而不是Mysql
然后修改:
u.Incry("Money" , +1)
u.Save() //同步到数据库。 不执行 只变更redis
u.Set("Money" , "aaaaaa") //修改.
u.Save()
这样, 这个orm 算是实现了。 很多细节, 这里不多说。待续。
项目Github地址:http://github.com/ablegao/orm
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。