Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -21,7 +21,7 @@ So to mitigate all the problems that Google faced with the current tools, they w
|
||||
|
||||
Go was designed with concurrency in mind, please note that parallelism != concurrency, there is an amazing post by Rob Pike on the golang blog, blog.golang.org, you will find it there, it is worth a read.
|
||||
|
||||
Another very important change that go has brought in programming that I personally love is the concept of `GOPATH`, gone are the days when you had to create a folder called `code` and then create workspaces for eclipse and what not, not you have to keep one folder tree for go code and it'll be updated by the package manager automatically. Also under the code we are recommended to create folders with either a custom domain or the github domain, for example I created a task manager using golang so I created a set of folders
|
||||
Another very important change that go has brought in programming that I personally love is the concept of `GOPATH`, gone are the days when you had to create a folder called `code` and then create workspaces for eclipse and what not, now you have to keep one folder tree for go code and it'll be updated by the package manager automatically. Also under the code we are recommended to create folders with either a custom domain or the github domain, for example I created a task manager using golang so I created a set of folders
|
||||
`~/go/src/github.com/thewhitetulip/Tasks` note: In *nix systems `~` stands for home directory, which is the windows equivalent of `C:\\Users\\username`
|
||||
now the `~/go/` is the universe for the gocode in your machine, it is just a significant improvement over other languages so we can store the code efficiently without hassles, it might seem strange at first, but it does make a lot of sense over the ridiculous package names some other languages use like reverse domains.
|
||||
|
||||
|
||||
449
zh/05.5.md
449
zh/05.5.md
@@ -1,7 +1,7 @@
|
||||
# 5.5 使用beedb/beego orm(暂未完成,请参考beego.me文档)库进行ORM开发
|
||||
beedb/beego orm是我开发的一个Go进行ORM操作的库,它采用了Go style方式对数据库进行操作,实现了struct到数据表记录的映射。beedb是一个十分轻量级的Go ORM框架,开发这个库的本意降低复杂的ORM学习曲线,尽可能在ORM的运行效率和功能之间寻求一个平衡,beedb是目前开源的Go ORM框架中实现比较完整的一个库,而且运行效率相当不错,功能也基本能满足需求。但是目前还不支持关系关联,这个是接下来版本升级的重点。
|
||||
# 5.5 使用Beego orm库进行ORM开发
|
||||
beego orm是我开发的一个Go进行ORM操作的库,它采用了Go style方式对数据库进行操作,实现了struct到数据表记录的映射。beego orm是一个十分轻量级的Go ORM框架,开发这个库的本意降低复杂的ORM学习曲线,尽可能在ORM的运行效率和功能之间寻求一个平衡,beego orm是目前开源的Go ORM框架中实现比较完整的一个库,而且运行效率相当不错,功能也基本能满足需求。
|
||||
|
||||
beedb/beego orm是支持database/sql标准接口的ORM库,所以理论上来说,只要数据库驱动支持database/sql接口就可以无缝的接入beedb。目前我测试过的驱动包括下面几个:
|
||||
beego orm是支持database/sql标准接口的ORM库,所以理论上来说,只要数据库驱动支持database/sql接口就可以无缝的接入beego orm。目前我测试过的驱动包括下面几个:
|
||||
|
||||
|
||||
Mysql: [github/go-mysql-driver/mysql](https://github.com/go-sql-driver/mysql)
|
||||
@@ -12,6 +12,9 @@ SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
|
||||
|
||||
Mysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql)
|
||||
|
||||
|
||||
暂未支持数据库:
|
||||
|
||||
MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
|
||||
|
||||
MS ADODB: [github.com/mattn/go-adodb](https://github.com/mattn/go-adodb)
|
||||
@@ -27,10 +30,6 @@ beego orm支持go get方式安装,是完全按照Go Style的方式来实现的
|
||||
|
||||
go get github.com/astaxie/beego
|
||||
|
||||
beedb支持go get方式安装,是完全按照Go Style的方式来实现的。
|
||||
|
||||
go get github.com/astaxie/beedb
|
||||
|
||||
## 如何初始化
|
||||
首先你需要import相应的数据库驱动包、database/sql标准接口包以及beego orm包,如下所示:
|
||||
```Go
|
||||
@@ -40,50 +39,146 @@ beedb支持go get方式安装,是完全按照Go Style的方式来实现的。
|
||||
"github.com/astaxie/beego/orm"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 设置默认数据库
|
||||
orm.RegisterDataBase("default", "mysql", "root:root@/my_db?charset=utf8", 30)
|
||||
//注册定义的model
|
||||
orm.RegisterModel(new(User))
|
||||
|
||||
// 创建table
|
||||
orm.RunSyncdb("default", false, true)
|
||||
}
|
||||
```
|
||||
|
||||
PostgreSQL 配置:
|
||||
|
||||
```Go
|
||||
//导入驱动
|
||||
// _ "github.com/lib/pq"
|
||||
|
||||
// 注册驱动
|
||||
orm.RegisterDriver("postgres", orm.DR_Postgres)
|
||||
|
||||
// 设置默认数据库
|
||||
//PostgresQL用户:postgres ,密码:zxxx , 数据库名称:test , 数据库别名:default
|
||||
orm.RegisterDataBase("default", "postgres", "user=postgres password=zxxx dbname=test host=127.0.0.1 port=5432 sslmode=disable")
|
||||
```
|
||||
|
||||
MySQL 配置:
|
||||
|
||||
```Go
|
||||
//导入驱动
|
||||
//_ "github.com/go-sql-driver/mysql"
|
||||
|
||||
//注册驱动
|
||||
orm.RegisterDriver("mysql", orm.DR_MySQL)
|
||||
|
||||
// 设置默认数据库
|
||||
//mysql用户:root ,密码:zxxx , 数据库名称:test , 数据库别名:default
|
||||
orm.RegisterDataBase("default", "mysql", "root:zxxx@/test?charset=utf8")
|
||||
```
|
||||
Sqlite 配置:
|
||||
```Go
|
||||
//导入驱动
|
||||
//_ "github.com/mattn/go-sqlite3"
|
||||
|
||||
//注册驱动
|
||||
orm.RegisterDriver("sqlite", orm.DR_Sqlite)
|
||||
|
||||
// 设置默认数据库
|
||||
//数据库存放位置:./datas/test.db , 数据库别名:default
|
||||
orm.RegisterDataBase("default", "sqlite3", "./datas/test.db")
|
||||
```
|
||||
|
||||
导入必须的package之后,我们需要打开到数据库的链接,然后创建一个beego orm对象(以MySQL为例),如下所示
|
||||
beego orm:
|
||||
|
||||
```Go
|
||||
|
||||
func init() {
|
||||
// set default database
|
||||
orm.RegisterDataBase("default", "mysql", "root:root@/my_db?charset=utf8", 30)
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
orm := orm.NewOrm()
|
||||
}
|
||||
```
|
||||
|
||||
beedb:
|
||||
|
||||
```Go
|
||||
db, err := sql.Open("mymysql", "test/xiemengjun/123456")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
orm := beedb.New(db)
|
||||
```
|
||||
beedb的New函数实际上应该有两个参数,第一个参数标准接口的db,第二个参数是使用的数据库引擎,如果你使用的数据库引擎是MySQL/Sqlite,那么第二个参数都可以省略。
|
||||
|
||||
如果你使用的数据库是SQLServer,那么初始化需要:
|
||||
简单示例:
|
||||
```Go
|
||||
|
||||
orm = beedb.New(db, "mssql")
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/astaxie/beego/orm"
|
||||
_ "github.com/go-sql-driver/mysql" // 导入数据库驱动
|
||||
)
|
||||
|
||||
// Model Struct
|
||||
type User struct {
|
||||
Id int
|
||||
Name string `orm:"size(100)"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 设置默认数据库
|
||||
orm.RegisterDataBase("default", "mysql", "root:root@/my_db?charset=utf8", 30)
|
||||
|
||||
// 注册定义的 model
|
||||
orm.RegisterModel(new(User))
|
||||
//RegisterModel 也可以同时注册多个 model
|
||||
//orm.RegisterModel(new(User), new(Profile), new(Post))
|
||||
|
||||
// 创建 table
|
||||
orm.RunSyncdb("default", false, true)
|
||||
}
|
||||
|
||||
func main() {
|
||||
o := orm.NewOrm()
|
||||
|
||||
user := User{Name: "slene"}
|
||||
|
||||
// 插入表
|
||||
id, err := o.Insert(&user)
|
||||
fmt.Printf("ID: %d, ERR: %v\n", id, err)
|
||||
|
||||
// 更新表
|
||||
user.Name = "astaxie"
|
||||
num, err := o.Update(&user)
|
||||
fmt.Printf("NUM: %d, ERR: %v\n", num, err)
|
||||
|
||||
// 读取 one
|
||||
u := User{Id: user.Id}
|
||||
err = o.Read(&u)
|
||||
fmt.Printf("ERR: %v\n", err)
|
||||
|
||||
// 删除表
|
||||
num, err = o.Delete(&u)
|
||||
fmt.Printf("NUM: %d, ERR: %v\n", num, err)
|
||||
}
|
||||
|
||||
```
|
||||
如果你使用了PostgreSQL,那么初始化需要:
|
||||
|
||||
SetMaxIdleConns
|
||||
|
||||
根据数据库的别名,设置数据库的最大空闲连接
|
||||
```Go
|
||||
|
||||
orm = beedb.New(db, "pg")
|
||||
orm.SetMaxIdleConns("default", 30)
|
||||
```
|
||||
目前beedb支持打印调试,你可以通过如下的代码实现调试
|
||||
SetMaxOpenConns
|
||||
|
||||
根据数据库的别名,设置数据库的最大数据库连接 (go >= 1.2)
|
||||
```Go
|
||||
|
||||
beedb.OnDebug=true
|
||||
orm.SetMaxOpenConns("default", 30)
|
||||
```
|
||||
接下来我们的例子采用前面的数据库表Userinfo,现在我们建立相应的struct
|
||||
|
||||
目前beego orm支持打印调试,你可以通过如下的代码实现调试
|
||||
```Go
|
||||
|
||||
orm.Debug = true
|
||||
```
|
||||
|
||||
接下来我们的例子采用前面的数据库表User,现在我们建立相应的struct
|
||||
```Go
|
||||
|
||||
type Userinfo struct {
|
||||
@@ -93,139 +188,167 @@ beedb的New函数实际上应该有两个参数,第一个参数标准接口的
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
type User struct {
|
||||
Uid int `PK` //如果表的主键不是id,那么需要加上pk注释,显式的说这个字段是主键
|
||||
Name string
|
||||
Profile *Profile `orm:"rel(one)"` // OneToOne relation
|
||||
Post []*Post `orm:"reverse(many)"` // 设置一对多的反向关系
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
Id int
|
||||
Age int16
|
||||
User *User `orm:"reverse(one)"` // 设置一对一反向关系(可选)
|
||||
}
|
||||
|
||||
type Post struct {
|
||||
Id int
|
||||
Title string
|
||||
User *User `orm:"rel(fk)"` //设置一对多关系
|
||||
Tags []*Tag `orm:"rel(m2m)"`
|
||||
}
|
||||
|
||||
type Tag struct {
|
||||
Id int
|
||||
Name string
|
||||
Posts []*Post `orm:"reverse(many)"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
// 需要在init中注册定义的model
|
||||
orm.RegisterModel(new(Userinfo),new(User), new(Profile), new(Tag))
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
>注意一点,beego orm针对驼峰命名会自动帮你转化成下划线字段,例如你定义了Struct名字为`UserInfo`,那么转化成底层实现的时候是`user_info`,字段命名也遵循该规则。
|
||||
>注意一点,beego orm针对驼峰命名会自动帮你转化成下划线字段,例如你定义了Struct名字为`User`,那么转化成底层实现的时候是`user_info`,字段命名也遵循该规则。
|
||||
|
||||
## 插入数据
|
||||
下面的代码演示了如何插入一条记录,可以看到我们操作的是struct对象,而不是原生的sql语句,最后通过调用Save接口将数据保存到数据库。
|
||||
下面的代码演示了如何插入一条记录,可以看到我们操作的是struct对象,而不是原生的sql语句,最后通过调用Insert接口将数据保存到数据库。
|
||||
```Go
|
||||
|
||||
var saveone Userinfo
|
||||
saveone.Username = "Test Add User"
|
||||
saveone.Departname = "Test Add Departname"
|
||||
saveone.Created = time.Now()
|
||||
orm.Save(&saveone)
|
||||
```
|
||||
我们看到插入之后`saveone.Uid`就是插入成功之后的自增ID。Save接口会自动帮你存进去。
|
||||
o := orm.NewOrm()
|
||||
var user User
|
||||
user.Name = "zxxx"
|
||||
user.Departname = "zxxx"
|
||||
|
||||
beedb接口提供了另外一种插入的方式,map数据插入。
|
||||
id, err := o.Insert(&user)
|
||||
if err == nil {
|
||||
fmt.Println(id)
|
||||
}
|
||||
```
|
||||
我们看到插入之后`user.Uid`就是插入成功之后的自增ID。
|
||||
|
||||
|
||||
同时插入多个对象:InsertMulti
|
||||
|
||||
类似sql语句
|
||||
```Go
|
||||
|
||||
add := make(map[string]interface{})
|
||||
add["username"] = "astaxie"
|
||||
add["departname"] = "cloud develop"
|
||||
add["created"] = "2012-12-02"
|
||||
orm.SetTable("userinfo").Insert(add)
|
||||
insert into table (name, age) values("slene", 28),("astaxie", 30),("unknown", 20)
|
||||
```
|
||||
插入多条数据
|
||||
第一个参数 bulk 为并列插入的数量,第二个为对象的slice
|
||||
|
||||
返回值为成功插入的数量
|
||||
```Go
|
||||
|
||||
addslice := make([]map[string]interface{}, 0)
|
||||
add:=make(map[string]interface{})
|
||||
add2:=make(map[string]interface{})
|
||||
add["username"] = "astaxie"
|
||||
add["departname"] = "cloud develop"
|
||||
add["created"] = "2012-12-02"
|
||||
add2["username"] = "astaxie2"
|
||||
add2["departname"] = "cloud develop2"
|
||||
add2["created"] = "2012-12-02"
|
||||
addslice =append(addslice, add, add2)
|
||||
orm.SetTable("userinfo").InsertBatch(addslice)
|
||||
users := []User{
|
||||
{Name: "slene"},
|
||||
{Name: "astaxie"},
|
||||
{Name: "unknown"},
|
||||
...
|
||||
}
|
||||
successNums, err := o.InsertMulti(100, users)
|
||||
```
|
||||
上面的操作方式有点类似链式查询,熟悉jquery的同学应该会觉得很亲切,每次调用的method都会返回原orm对象,以便可以继续调用该对象上的其他method。
|
||||
bulk 为 1 时,将会顺序插入 slice 中的数据
|
||||
|
||||
上面我们调用的SetTable函数是显式的告诉ORM,我要执行的这个map对应的数据库表是`userinfo`。
|
||||
|
||||
## 更新数据
|
||||
继续上面的例子来演示更新操作,现在saveone的主键已经有值了,此时调用save接口,beedb内部会自动调用update以进行数据的更新而非插入操作。
|
||||
继续上面的例子来演示更新操作,现在user的主键已经有值了,此时调用Insert接口,beego orm内部会自动调用update以进行数据的更新而非插入操作。
|
||||
```Go
|
||||
|
||||
saveone.Username = "Update Username"
|
||||
saveone.Departname = "Update Departname"
|
||||
saveone.Created = time.Now()
|
||||
orm.Save(&saveone) //现在saveone有了主键值,就执行更新操作
|
||||
o := orm.NewOrm()
|
||||
user := User{Uid: 1}
|
||||
if o.Read(&user) == nil {
|
||||
user.Name = "MyName"
|
||||
if num, err := o.Update(&user); err == nil {
|
||||
fmt.Println(num)
|
||||
}
|
||||
}
|
||||
```
|
||||
更新数据也支持直接使用map操作
|
||||
Update 默认更新所有的字段,可以更新指定的字段:
|
||||
```Go
|
||||
|
||||
t := make(map[string]interface{})
|
||||
t["username"] = "astaxie"
|
||||
orm.SetTable("userinfo").SetPK("uid").Where(2).Update(t)
|
||||
// 只更新 Name
|
||||
o.Update(&user, "Name")
|
||||
// 指定多个字段
|
||||
// o.Update(&user, "Field1", "Field2", ...)
|
||||
```
|
||||
这里我们调用了几个beedb的函数
|
||||
|
||||
SetPK:显式的告诉ORM,数据库表`userinfo`的主键是`uid`。
|
||||
|
||||
Where:用来设置条件,支持多个参数,第一个参数如果为整数,相当于调用了Where("主键=?",值)。
|
||||
Updata函数接收map类型的数据,执行更新数据。
|
||||
//Where:用来设置条件,支持多个参数,第一个参数如果为整数,相当于调用了Where("主键=?",值)。
|
||||
|
||||
## 查询数据
|
||||
beedb的查询接口比较灵活,具体使用请看下面的例子
|
||||
beego orm的查询接口比较灵活,具体使用请看下面的例子
|
||||
|
||||
例子1,根据主键获取数据:
|
||||
```Go
|
||||
|
||||
var user Userinfo
|
||||
//Where接受两个参数,支持整形参数
|
||||
orm.Where("uid=?", 27).Find(&user)
|
||||
o := orm.NewOrm()
|
||||
var user User
|
||||
|
||||
user := User{Id: 1}
|
||||
|
||||
err = o.Read(&user)
|
||||
|
||||
if err == orm.ErrNoRows {
|
||||
fmt.Println("查询不到")
|
||||
} else if err == orm.ErrMissPK {
|
||||
fmt.Println("找不到主键")
|
||||
} else {
|
||||
fmt.Println(user.Id, user.Name)
|
||||
}
|
||||
```
|
||||
|
||||
例子2:
|
||||
```Go
|
||||
|
||||
var user2 Userinfo
|
||||
orm.Where(3).Find(&user2) // 这是上面版本的缩写版,可以省略主键
|
||||
o := orm.NewOrm()
|
||||
var user User
|
||||
|
||||
qs := o.QueryTable(user) // 返回 QuerySeter
|
||||
qs.Filter("id", 1) // WHERE id = 1
|
||||
qs.Filter("profile__age", 18) // WHERE profile.age = 18
|
||||
```
|
||||
例子3,不是主键类型的的条件:
|
||||
例子3,WHERE IN查询条件:
|
||||
```Go
|
||||
|
||||
var user3 Userinfo
|
||||
//Where接受两个参数,支持字符型的参数
|
||||
orm.Where("name = ?", "john").Find(&user3)
|
||||
qs.Filter("profile__age__in", 18, 20)
|
||||
// WHERE profile.age IN (18, 20)
|
||||
|
||||
```
|
||||
例子4,更加复杂的条件:
|
||||
```Go
|
||||
|
||||
var user4 Userinfo
|
||||
//Where支持三个参数
|
||||
orm.Where("name = ? and age < ?", "john", 88).Find(&user4)
|
||||
qs.Filter("profile__age__in", 18, 20).Exclude("profile__lt", 1000)
|
||||
// WHERE profile.age IN (18, 20) AND NOT profile_id < 1000
|
||||
|
||||
```
|
||||
|
||||
可以通过如下接口获取多条数据,请看示例
|
||||
|
||||
例子1,根据条件id>3,获取20位置开始的10条数据的数据
|
||||
例子1,根据条件age>17,获取20位置开始的10条数据的数据
|
||||
```Go
|
||||
|
||||
var allusers []Userinfo
|
||||
err := orm.Where("id > ?", "3").Limit(10,20).FindAll(&allusers)
|
||||
var allusers []User
|
||||
qs.Filter("profile__age__gt", 17)
|
||||
// WHERE profile.age > 17
|
||||
```
|
||||
例子2,省略limit第二个参数,默认从0开始,获取10条数据
|
||||
例子2,limit默认从10开始,获取10条数据
|
||||
```Go
|
||||
|
||||
var tenusers []Userinfo
|
||||
err := orm.Where("id > ?", "3").Limit(10).FindAll(&tenusers)
|
||||
qs.Limit(10, 20)
|
||||
// LIMIT 10 OFFSET 20 注意跟SQL反过来的
|
||||
```
|
||||
例子3,获取全部数据
|
||||
```Go
|
||||
|
||||
var everyone []Userinfo
|
||||
err := orm.OrderBy("uid desc,username asc").FindAll(&everyone)
|
||||
```
|
||||
上面这些里面里面我们看到一个函数Limit,他是用来控制查询结构条数的。
|
||||
|
||||
Limit:支持两个参数,第一个参数表示查询的条数,第二个参数表示读取数据的起始位置,默认为0。
|
||||
|
||||
OrderBy:这个函数用来进行查询排序,参数是需要排序的条件。
|
||||
|
||||
上面这些例子都是将获取的的数据直接映射成struct对象,如果我们只是想获取一些数据到map,以下方式可以实现:
|
||||
```Go
|
||||
|
||||
a, _ := orm.SetTable("userinfo").SetPK("uid").Where(2).Select("uid,username").FindMap()
|
||||
```
|
||||
上面和这个例子里面又出现了一个新的接口函数Select,这个函数用来指定需要查询多少个字段。默认为全部字段`*`。
|
||||
|
||||
FindMap()函数返回的是`[]map[string][]byte`类型,所以你需要自己作类型转换。
|
||||
|
||||
## 删除数据
|
||||
beedb提供了丰富的删除数据接口,请看下面的例子
|
||||
@@ -233,39 +356,42 @@ beedb提供了丰富的删除数据接口,请看下面的例子
|
||||
例子1,删除单条数据
|
||||
```Go
|
||||
|
||||
//saveone就是上面示例中的那个saveone
|
||||
orm.Delete(&saveone)
|
||||
```
|
||||
例子2,删除多条数据
|
||||
```Go
|
||||
|
||||
//alluser就是上面定义的获取多条数据的slice
|
||||
orm.DeleteAll(&alluser)
|
||||
```
|
||||
例子3,根据sql删除数据
|
||||
```Go
|
||||
|
||||
orm.SetTable("userinfo").Where("uid>?", 3).DeleteRow()
|
||||
o := orm.NewOrm()
|
||||
if num, err := o.Delete(&User{Id: 1}); err == nil {
|
||||
fmt.Println(num)
|
||||
}
|
||||
```
|
||||
Delete 操作会对反向关系进行操作,此例中 Post 拥有一个到 User 的外键。删除 User 的时候。如果 on_delete 设置为默认的级联操作,将删除对应的 Post
|
||||
|
||||
## 关联查询
|
||||
目前beedb还不支持struct的关联关系,但是有些应用却需要用到连接查询,所以现在beedb提供了一个简陋的实现方案:
|
||||
有些应用却需要用到连接查询,所以现在beego orm提供了一个简陋的实现方案:
|
||||
```Go
|
||||
|
||||
a, _ := orm.SetTable("userinfo").Join("LEFT", "userdeatail", "userinfo.uid=userdeatail.uid").Where("userinfo.uid=?", 1).Select("userinfo.uid,userinfo.username,userdeatail.profile").FindMap()
|
||||
```
|
||||
上面代码中我们看到了一个新的接口Join函数,这个函数带有三个参数
|
||||
type Post struct {
|
||||
Id int `orm:"auto"`
|
||||
Title string `orm:"size(100)"`
|
||||
User *User `orm:"rel(fk)"`
|
||||
}
|
||||
|
||||
var posts []*Post
|
||||
qs := o.QueryTable("post")
|
||||
num, err := qs.Filter("User__Name", "slene").All(&posts)
|
||||
|
||||
```
|
||||
上面代码中我们看到了一个struct关联查询
|
||||
|
||||
- 第一个参数可以是:INNER, LEFT, OUTER, CROSS等
|
||||
- 第二个参数表示连接的表
|
||||
- 第三个参数表示连接的条件
|
||||
|
||||
|
||||
## Group By和Having
|
||||
针对有些应用需要用到group by和having的功能,beedb也提供了一个简陋的实现
|
||||
针对有些应用需要用到group by的功能,beego orm也提供了一个简陋的实现
|
||||
```Go
|
||||
|
||||
a, _ := orm.SetTable("userinfo").GroupBy("username").Having("username='astaxie'").FindMap()
|
||||
qs.OrderBy("id", "-profile__age")
|
||||
// ORDER BY id ASC, profile.age DESC
|
||||
|
||||
qs.OrderBy("-profile__age", "profile")
|
||||
// ORDER BY profile.age DESC, profile_id ASC
|
||||
|
||||
```
|
||||
上面的代码中出现了两个新接口函数
|
||||
|
||||
@@ -273,28 +399,45 @@ GroupBy:用来指定进行groupby的字段
|
||||
|
||||
Having:用来指定having执行的时候的条件
|
||||
|
||||
## 进一步的发展
|
||||
目前beedb已经获得了很多来自国内外用户的反馈,我目前也正在考虑重构,接下来会在几个方面进行改进
|
||||
|
||||
- 实现interface设计,类似databse/sql/driver的设计,设计beedb的接口,然后去实现相应数据库的CRUD操作
|
||||
- 实现关联数据库设计,支持一对一,一对多,多对多的实现,示例代码如下:
|
||||
##使用原生sql
|
||||
|
||||
简单示例:
|
||||
|
||||
```Go
|
||||
|
||||
type Profile struct{
|
||||
Nickname string
|
||||
Mobile string
|
||||
}
|
||||
|
||||
type Userinfo struct {
|
||||
Uid int `PK`
|
||||
Username string
|
||||
Departname string
|
||||
Created time.Time
|
||||
Profile `HasOne`
|
||||
}
|
||||
o := NewOrm()
|
||||
var r RawSeter
|
||||
r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
|
||||
```
|
||||
- 自动建库建表建索引
|
||||
- 实现连接池的实现,采用goroutine
|
||||
|
||||
复杂原生sql使用:
|
||||
|
||||
```Go
|
||||
func (m *User) Query(name string) []User {
|
||||
var o orm.Ormer
|
||||
var rs orm.RawSeter
|
||||
o = orm.NewOrm()
|
||||
rs = o.Raw("SELECT * FROM user "+
|
||||
"WHERE name=? AND uid>10 "+
|
||||
"ORDER BY uid DESC "+
|
||||
"LIMIT 100", name)
|
||||
var user []User
|
||||
num, err := rs.QueryRows(&user)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println(num)
|
||||
return user
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
更多说明,请到[beego.me](https://beego.me)
|
||||
|
||||
## 进一步的发展
|
||||
目前beego orm已经获得了很多来自国内外用户的反馈,我目前也正在考虑支持更多数据库,接下来会在更多方面进行改进
|
||||
|
||||
|
||||
## links
|
||||
* [目录](<preface.md>)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
* 1.[Go环境配置](01.0.md)
|
||||
- 1.1. [Go安装](01.1.md)
|
||||
- 1.1. [安装Go](01.1.md)
|
||||
- 1.2. [GOPATH 与工作空间](01.2.md)
|
||||
- 1.3. [Go 命令](01.3.md)
|
||||
- 1.4. [Go开发工具](01.4.md)
|
||||
@@ -31,7 +31,7 @@
|
||||
- 5.2 [使用MySQL数据库](05.2.md)
|
||||
- 5.3 [使用SQLite数据库](05.3.md)
|
||||
- 5.4 [使用PostgreSQL数据库](05.4.md)
|
||||
- 5.5 [使用beedb库进行ORM开发](05.5.md)
|
||||
- 5.5 [使用Beego orm库进行ORM开发](05.5.md)
|
||||
- 5.6 [NOSQL数据库操作](05.6.md)
|
||||
- 5.7 [小结](05.7.md)
|
||||
* 6.[session和数据存储](06.0.md)
|
||||
|
||||
Reference in New Issue
Block a user