mirror of
https://github.com/astaxie/beego.git
synced 2024-11-26 12:51:29 +00:00
orm: delete the old docs
This commit is contained in:
parent
e7fcb824c1
commit
7ddd20340b
@ -1,43 +0,0 @@
|
|||||||
## 命令模式
|
|
||||||
|
|
||||||
注册模型与数据库以后,调用 RunCommand 执行 orm 命令
|
|
||||||
|
|
||||||
```go
|
|
||||||
func main() {
|
|
||||||
// orm.RegisterModel...
|
|
||||||
// orm.RegisterDataBase...
|
|
||||||
...
|
|
||||||
orm.RunCommand()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build main.go
|
|
||||||
./main orm
|
|
||||||
# 直接执行可以显示帮助
|
|
||||||
# 如果你的程序可以支持的话,直接运行 go run main.go orm 也是一样的效果
|
|
||||||
```
|
|
||||||
|
|
||||||
## 自动建表
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./main orm syncdb -h
|
|
||||||
Usage of orm command: syncdb:
|
|
||||||
-db="default": DataBase alias name
|
|
||||||
-force=false: drop tables before create
|
|
||||||
-v=false: verbose info
|
|
||||||
```
|
|
||||||
|
|
||||||
使用 `-force=1` 可以 drop table 后再建表
|
|
||||||
|
|
||||||
使用 `-v` 可以查看执行的 sql 语句
|
|
||||||
|
|
||||||
## 打印建表SQL
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./main orm sqlall -h
|
|
||||||
Usage of orm command: syncdb:
|
|
||||||
-db="default": DataBase alias name
|
|
||||||
```
|
|
||||||
|
|
||||||
默认使用别名为 default 的数据库
|
|
@ -1,38 +0,0 @@
|
|||||||
## Custom Fields
|
|
||||||
|
|
||||||
TypeBooleanField = 1 << iota
|
|
||||||
|
|
||||||
// string
|
|
||||||
TypeCharField
|
|
||||||
|
|
||||||
// string
|
|
||||||
TypeTextField
|
|
||||||
|
|
||||||
// time.Time
|
|
||||||
TypeDateField
|
|
||||||
// time.Time
|
|
||||||
TypeDateTimeField
|
|
||||||
|
|
||||||
// int16
|
|
||||||
TypeSmallIntegerField
|
|
||||||
// int32
|
|
||||||
TypeIntegerField
|
|
||||||
// int64
|
|
||||||
TypeBigIntegerField
|
|
||||||
// uint16
|
|
||||||
TypePositiveSmallIntegerField
|
|
||||||
// uint32
|
|
||||||
TypePositiveIntegerField
|
|
||||||
// uint64
|
|
||||||
TypePositiveBigIntegerField
|
|
||||||
|
|
||||||
// float64
|
|
||||||
TypeFloatField
|
|
||||||
// float64
|
|
||||||
TypeDecimalField
|
|
||||||
|
|
||||||
RelForeignKey
|
|
||||||
RelOneToOne
|
|
||||||
RelManyToMany
|
|
||||||
RelReverseOne
|
|
||||||
RelReverseMany
|
|
@ -1,288 +0,0 @@
|
|||||||
## 模型定义
|
|
||||||
|
|
||||||
复杂的模型定义不是必须的,此功能用作数据库数据转换和[自动建表](Cmd.md#自动建表)
|
|
||||||
|
|
||||||
默认的表名使用驼峰转蛇形,比如 AuthUser -> auth_user
|
|
||||||
|
|
||||||
**自定义表名**
|
|
||||||
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
Id int
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) TableName() string {
|
|
||||||
return "auth_user"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
如果[前缀设置](Orm.md#registermodelwithprefix)为`prefix_`那么表名为:prefix_auth_user
|
|
||||||
|
|
||||||
## Struct Tag 设置参数
|
|
||||||
```go
|
|
||||||
orm:"null;rel(fk)"
|
|
||||||
```
|
|
||||||
|
|
||||||
多个设置间使用 `;` 分隔,设置的值如果是多个,使用 `,` 分隔。
|
|
||||||
|
|
||||||
#### 忽略字段
|
|
||||||
|
|
||||||
设置 `-` 即可忽略 struct 中的字段
|
|
||||||
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
...
|
|
||||||
AnyField string `orm:"-"`
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
#### auto
|
|
||||||
|
|
||||||
当 Field 类型为 int, int32, int64 时,可以设置字段为自增健
|
|
||||||
|
|
||||||
当模型定义里没有主键时,符合上述类型且名称为 `Id` 的 Field 将被视为自增健。
|
|
||||||
|
|
||||||
#### pk
|
|
||||||
|
|
||||||
设置为主键,适用于自定义其他类型为主键
|
|
||||||
|
|
||||||
#### null
|
|
||||||
|
|
||||||
数据库表默认为 `NOT NULL`,设置 null 代表 `ALLOW NULL`
|
|
||||||
|
|
||||||
#### blank
|
|
||||||
|
|
||||||
设置 string 类型的字段允许为空,否则 clean 会返回错误
|
|
||||||
|
|
||||||
#### index
|
|
||||||
|
|
||||||
为字段增加索引
|
|
||||||
|
|
||||||
#### unique
|
|
||||||
|
|
||||||
为字段增加 unique 键
|
|
||||||
|
|
||||||
#### column
|
|
||||||
|
|
||||||
为字段设置 db 字段的名称
|
|
||||||
```go
|
|
||||||
Name `orm:"column(user_name)"`
|
|
||||||
```
|
|
||||||
#### default
|
|
||||||
|
|
||||||
为字段设置默认值,类型必须符合
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
...
|
|
||||||
Status int `orm:"default(1)"`
|
|
||||||
```
|
|
||||||
#### size
|
|
||||||
|
|
||||||
string 类型字段默认为 varchar(255)
|
|
||||||
|
|
||||||
设置 size 以后,db type 将使用 varchar(size)
|
|
||||||
|
|
||||||
```go
|
|
||||||
Title string `orm:"size(60)"`
|
|
||||||
```
|
|
||||||
#### digits / decimals
|
|
||||||
|
|
||||||
设置 float32, float64 类型的浮点精度
|
|
||||||
```go
|
|
||||||
Money float64 `orm:"digits(12);decimals(4)"`
|
|
||||||
```
|
|
||||||
总长度 12 小数点后 4 位 eg: `99999999.9999`
|
|
||||||
|
|
||||||
#### auto_now / auto_now_add
|
|
||||||
```go
|
|
||||||
Created time.Time `auto_now_add`
|
|
||||||
Updated time.Time `auto_now`
|
|
||||||
```
|
|
||||||
* auto_now 每次 model 保存时都会对时间自动更新
|
|
||||||
* auto_now_add 第一次保存时才设置时间
|
|
||||||
|
|
||||||
对于批量的 update 此设置是不生效的
|
|
||||||
|
|
||||||
#### type
|
|
||||||
|
|
||||||
设置为 date 时,time.Time 字段的对应 db 类型使用 date
|
|
||||||
|
|
||||||
```go
|
|
||||||
Created time.Time `orm:"auto_now_add;type(date)"`
|
|
||||||
```
|
|
||||||
|
|
||||||
设置为 text 时,string 字段对应的 db 类型使用 text
|
|
||||||
|
|
||||||
```go
|
|
||||||
Content string `orm:"type(text)"`
|
|
||||||
```
|
|
||||||
|
|
||||||
## 表关系设置
|
|
||||||
|
|
||||||
#### rel / reverse
|
|
||||||
|
|
||||||
**RelOneToOne**:
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
...
|
|
||||||
Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
|
|
||||||
```
|
|
||||||
对应的反向关系 **RelReverseOne**:
|
|
||||||
```go
|
|
||||||
type Profile struct {
|
|
||||||
...
|
|
||||||
User *User `orm:"reverse(one)" json:"-"`
|
|
||||||
```
|
|
||||||
**RelForeignKey**:
|
|
||||||
```go
|
|
||||||
type Post struct {
|
|
||||||
...
|
|
||||||
User*User `orm:"rel(fk)"` // RelForeignKey relation
|
|
||||||
```
|
|
||||||
对应的反向关系 **RelReverseMany**:
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
...
|
|
||||||
Posts []*Post `orm:"reverse(many)" json:"-"` // fk 的反向关系
|
|
||||||
```
|
|
||||||
**RelManyToMany**:
|
|
||||||
```go
|
|
||||||
type Post struct {
|
|
||||||
...
|
|
||||||
Tags []*Tag `orm:"rel(m2m)"` // ManyToMany relation
|
|
||||||
```
|
|
||||||
对应的反向关系 **RelReverseMany**:
|
|
||||||
```go
|
|
||||||
type Tag struct {
|
|
||||||
...
|
|
||||||
Posts []*Post `orm:"reverse(many)" json:"-"`
|
|
||||||
```
|
|
||||||
#### rel_table / rel_through
|
|
||||||
|
|
||||||
此设置针对 `orm:"rel(m2m)"` 的关系字段
|
|
||||||
|
|
||||||
rel_table 设置自动生成的 m2m 关系表的名称
|
|
||||||
rel_through 如果要在 m2m 关系中使用自定义的 m2m 关系表
|
|
||||||
通过这个设置其名称,格式为 pkg.path.ModelName
|
|
||||||
eg: app.models.PostTagRel
|
|
||||||
PostTagRel 表需要有到 Post 和 Tag 的关系
|
|
||||||
|
|
||||||
当设置 rel_table 时会忽略 rel_through
|
|
||||||
|
|
||||||
#### on_delete
|
|
||||||
|
|
||||||
设置对应的 rel 关系删除时,如何处理关系字段。
|
|
||||||
|
|
||||||
cascade 级联删除(默认值)
|
|
||||||
set_null 设置为 NULL,需要设置 null = true
|
|
||||||
set_default 设置为默认值,需要设置 default 值
|
|
||||||
do_nothing 什么也不做,忽略
|
|
||||||
|
|
||||||
```go
|
|
||||||
type User struct {
|
|
||||||
...
|
|
||||||
Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
|
|
||||||
...
|
|
||||||
type Profile struct {
|
|
||||||
...
|
|
||||||
User *User `orm:"reverse(one)" json:"-"`
|
|
||||||
|
|
||||||
// 删除 Profile 时将设置 User.Profile 的数据库字段为 NULL
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## 模型字段与数据库类型的对应
|
|
||||||
|
|
||||||
在此列出 orm 推荐的对应数据库类型,自动建表功能也会以此为标准。
|
|
||||||
|
|
||||||
默认所有的字段都是 **NOT NULL**
|
|
||||||
|
|
||||||
#### MySQL
|
|
||||||
|
|
||||||
| go |mysql
|
|
||||||
| :--- | :---
|
|
||||||
| int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | integer AUTO_INCREMENT
|
|
||||||
| bool | bool
|
|
||||||
| string - 默认为 size 255 | varchar(size)
|
|
||||||
| string - 设置 type(text) 时 | longtext
|
|
||||||
| time.Time - 设置 type 为 date 时 | date
|
|
||||||
| time.TIme | datetime
|
|
||||||
| byte | tinyint unsigned
|
|
||||||
| rune | integer
|
|
||||||
| int | integer
|
|
||||||
| int8 | tinyint
|
|
||||||
| int16 | smallint
|
|
||||||
| int32 | integer
|
|
||||||
| int64 | bigint
|
|
||||||
| uint | integer unsigned
|
|
||||||
| uint8 | tinyint unsigned
|
|
||||||
| uint16 | smallint unsigned
|
|
||||||
| uint32 | integer unsigned
|
|
||||||
| uint64 | bigint unsigned
|
|
||||||
| float32 | double precision
|
|
||||||
| float64 | double precision
|
|
||||||
| float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
|
|
||||||
|
|
||||||
#### Sqlite3
|
|
||||||
|
|
||||||
| go | sqlite3
|
|
||||||
| :--- | :---
|
|
||||||
| int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | integer AUTOINCREMENT
|
|
||||||
| bool | bool
|
|
||||||
| string - 默认为 size 255 | varchar(size)
|
|
||||||
| string - 设置 type(text) 时 | text
|
|
||||||
| time.Time - 设置 type 为 date 时 | date
|
|
||||||
| time.TIme | datetime
|
|
||||||
| byte | tinyint unsigned
|
|
||||||
| rune | integer
|
|
||||||
| int | integer
|
|
||||||
| int8 | tinyint
|
|
||||||
| int16 | smallint
|
|
||||||
| int32 | integer
|
|
||||||
| int64 | bigint
|
|
||||||
| uint | integer unsigned
|
|
||||||
| uint8 | tinyint unsigned
|
|
||||||
| uint16 | smallint unsigned
|
|
||||||
| uint32 | integer unsigned
|
|
||||||
| uint64 | bigint unsigned
|
|
||||||
| float32 | real
|
|
||||||
| float64 | real
|
|
||||||
| float64 - 设置 digits, decimals 时 | decimal
|
|
||||||
|
|
||||||
#### PostgreSQL
|
|
||||||
|
|
||||||
| go | postgres
|
|
||||||
| :--- | :---
|
|
||||||
| int, int32, int64 - 设置 auto 或者名称为 `Id` 时 | serial
|
|
||||||
| bool | bool
|
|
||||||
| string - 默认为 size 255 | varchar(size)
|
|
||||||
| string - 设置 type(text) 时 | text
|
|
||||||
| time.Time - 设置 type 为 date 时 | date
|
|
||||||
| time.TIme | timestamp with time zone
|
|
||||||
| byte | smallint CHECK("column" >= 0 AND "column" <= 255)
|
|
||||||
| rune | integer
|
|
||||||
| int | integer
|
|
||||||
| int8 | smallint CHECK("column" >= -127 AND "column" <= 128)
|
|
||||||
| int16 | smallint
|
|
||||||
| int32 | integer
|
|
||||||
| int64 | bigint
|
|
||||||
| uint | bigint CHECK("column" >= 0)
|
|
||||||
| uint8 | smallint CHECK("column" >= 0 AND "column" <= 255)
|
|
||||||
| uint16 | integer CHECK("column" >= 0)
|
|
||||||
| uint32 | bigint CHECK("column" >= 0)
|
|
||||||
| uint64 | bigint CHECK("column" >= 0)
|
|
||||||
| float32 | double precision
|
|
||||||
| float64 | double precision
|
|
||||||
| float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
|
|
||||||
|
|
||||||
|
|
||||||
## 关系型字段
|
|
||||||
|
|
||||||
其字段类型取决于对应的主键。
|
|
||||||
|
|
||||||
* RelForeignKey
|
|
||||||
* RelOneToOne
|
|
||||||
* RelManyToMany
|
|
||||||
* RelReverseOne
|
|
||||||
* RelReverseMany
|
|
@ -1,83 +0,0 @@
|
|||||||
SET NAMES utf8;
|
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for `comment`
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `comment`;
|
|
||||||
CREATE TABLE `comment` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`post_id` bigint(200) NOT NULL,
|
|
||||||
`content` longtext NOT NULL,
|
|
||||||
`parent_id` int(11) DEFAULT NULL,
|
|
||||||
`status` smallint(4) NOT NULL,
|
|
||||||
`created` datetime NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for `post`
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `post`;
|
|
||||||
CREATE TABLE `post` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`user_id` int(11) NOT NULL,
|
|
||||||
`title` varchar(60) NOT NULL,
|
|
||||||
`content` longtext NOT NULL,
|
|
||||||
`created` datetime NOT NULL,
|
|
||||||
`updated` datetime NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for `post_tag_rel`
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `post_tag_rel`;
|
|
||||||
CREATE TABLE `post_tag_rel` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`post_id` int(11) NOT NULL,
|
|
||||||
`tag_id` int(11) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for `tag`
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `tag`;
|
|
||||||
CREATE TABLE `tag` (
|
|
||||||
`id` int(11) NOT NULL,
|
|
||||||
`name` varchar(30) NOT NULL,
|
|
||||||
`status` smallint(4) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for `user`
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `user`;
|
|
||||||
CREATE TABLE `user` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`user_name` varchar(30) NOT NULL,
|
|
||||||
`email` varchar(100) NOT NULL,
|
|
||||||
`password` varchar(30) NOT NULL,
|
|
||||||
`status` smallint(4) NOT NULL,
|
|
||||||
`is_staff` tinyint(1) NOT NULL,
|
|
||||||
`is_active` tinyint(1) NOT NULL,
|
|
||||||
`created` date NOT NULL,
|
|
||||||
`updated` datetime NOT NULL,
|
|
||||||
`profile_id` int(11) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for `profile`
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `profile`;
|
|
||||||
CREATE TABLE `profile` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`age` smallint(4) NOT NULL,
|
|
||||||
`money` double NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
|
@ -1,59 +0,0 @@
|
|||||||
## 对象的CRUD操作
|
|
||||||
|
|
||||||
对 object 操作简单的三个方法 Read / Insert / Update / Delete
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
user := new(User)
|
|
||||||
user.Name = "slene"
|
|
||||||
|
|
||||||
fmt.Println(o.Insert(user))
|
|
||||||
|
|
||||||
user.Name = "Your"
|
|
||||||
fmt.Println(o.Update(user))
|
|
||||||
fmt.Println(o.Read(user))
|
|
||||||
fmt.Println(o.Delete(user))
|
|
||||||
```
|
|
||||||
### Read
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
user := User{Id: 1}
|
|
||||||
|
|
||||||
err = o.Read(&user)
|
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
|
||||||
fmt.Println("查询不到")
|
|
||||||
} else if err == orm.ErrMissPK {
|
|
||||||
fmt.Println("找不到主键")
|
|
||||||
} else {
|
|
||||||
fmt.Println(user.Id, user.Name)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
### Insert
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
var user User
|
|
||||||
user.Name = "slene"
|
|
||||||
user.IsActive = true
|
|
||||||
|
|
||||||
fmt.Println(o.Insert(&user))
|
|
||||||
fmt.Println(user.Id)
|
|
||||||
```
|
|
||||||
创建后会自动对 auto 的 field 赋值
|
|
||||||
|
|
||||||
### Update
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
user := User{Id: 1}
|
|
||||||
if o.Read(&user) == nil {
|
|
||||||
user.Name = "MyName"
|
|
||||||
o.Update(&user)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
### Delete
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
o.Delete(&User{Id: 1})
|
|
||||||
```
|
|
||||||
Delete 操作会对反向关系进行操作,此例中 Post 拥有一个到 User 的外键。删除 User 的时候。如果 on_delete 设置为默认的级联操作,将删除对应的 Post
|
|
||||||
|
|
||||||
删除以后会清除 auto field 的值
|
|
@ -1,316 +0,0 @@
|
|||||||
## Orm 使用方法
|
|
||||||
|
|
||||||
beego/orm 的使用例子
|
|
||||||
|
|
||||||
后文例子如无特殊说明都以这个为基础。
|
|
||||||
|
|
||||||
##### models.go:
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/astaxie/beego/orm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
Id int
|
|
||||||
Name string
|
|
||||||
Profile *Profile `orm:"rel(one)"` // OneToOne relation
|
|
||||||
}
|
|
||||||
|
|
||||||
type Profile struct {
|
|
||||||
Id int
|
|
||||||
Age int16
|
|
||||||
User *User `orm:"reverse(one)"` // 设置反向关系(可选)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// 需要在init中注册定义的model
|
|
||||||
orm.RegisterModel(new(User), new(Profile))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
##### main.go
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/astaxie/beego/orm"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
orm.RegisterDriver("mysql", orm.DR_MySQL)
|
|
||||||
|
|
||||||
orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
o := orm.NewOrm()
|
|
||||||
o.Using("default") // 默认使用 default,你可以指定为其他数据库
|
|
||||||
|
|
||||||
profile := new(Profile)
|
|
||||||
profile.Age = 30
|
|
||||||
|
|
||||||
user := new(User)
|
|
||||||
user.Profile = profile
|
|
||||||
user.Name = "slene"
|
|
||||||
|
|
||||||
fmt.Println(o.Insert(profile))
|
|
||||||
fmt.Println(o.Insert(user))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 数据库的设置
|
|
||||||
|
|
||||||
目前 orm 支持三种数据库,以下为测试过的 driver
|
|
||||||
|
|
||||||
将你需要使用的 driver 加入 import 中
|
|
||||||
|
|
||||||
```go
|
|
||||||
import (
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
_ "github.com/lib/pq"
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### RegisterDriver
|
|
||||||
|
|
||||||
三种默认数据库类型
|
|
||||||
|
|
||||||
```go
|
|
||||||
orm.DR_MySQL
|
|
||||||
orm.DR_Sqlite
|
|
||||||
orm.DR_Postgres
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
// 参数1 driverName
|
|
||||||
// 参数2 数据库类型
|
|
||||||
// 这个用来设置 driverName 对应的数据库类型
|
|
||||||
// mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置
|
|
||||||
orm.RegisterDriver("mymysql", orm.DR_MySQL)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### RegisterDataBase
|
|
||||||
|
|
||||||
orm 必须注册一个别名为 `default` 的数据库,作为默认使用。
|
|
||||||
|
|
||||||
```go
|
|
||||||
// 参数1 数据库的别名,用来在orm中切换数据库使用
|
|
||||||
// 参数2 driverName
|
|
||||||
// 参数3 对应的链接字符串
|
|
||||||
// 参数4 设置最大的空闲连接数,使用 golang 自己的连接池
|
|
||||||
orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 时区设置
|
|
||||||
|
|
||||||
orm 默认使用 time.Local 本地时区
|
|
||||||
|
|
||||||
* 作用于 orm 自动创建的时间
|
|
||||||
* 从数据库中取回的时间转换成 orm 本地时间
|
|
||||||
|
|
||||||
如果需要的话,你也可以进行更改
|
|
||||||
|
|
||||||
```go
|
|
||||||
// 设置为 UTC 时间
|
|
||||||
orm.DefaultTimeLoc = time.UTC
|
|
||||||
```
|
|
||||||
|
|
||||||
orm 在进行 RegisterDataBase 的同时,会获取数据库使用的时区,然后在 time.Time 类型存取的时做相应转换,以匹配时间系统,从而保证时间不会出错。
|
|
||||||
|
|
||||||
**注意:** 鉴于 Sqlite3 的设计,存取默认都为 UTC 时间
|
|
||||||
|
|
||||||
## 注册模型
|
|
||||||
|
|
||||||
如果使用 orm.QuerySeter 进行高级查询的话,这个是必须的。
|
|
||||||
|
|
||||||
反之,如果只使用 Raw 查询和 map struct,是无需这一步的。您可以去查看 [Raw SQL 查询](Raw.md)
|
|
||||||
|
|
||||||
#### RegisterModel
|
|
||||||
|
|
||||||
将你定义的 Model 进行注册,最佳设计是有单独的 models.go 文件,在他的 init 函数中进行注册。
|
|
||||||
|
|
||||||
|
|
||||||
迷你版 models.go
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import "github.com/astaxie/beego/orm"
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
Id int
|
|
||||||
Name string
|
|
||||||
}
|
|
||||||
|
|
||||||
func init(){
|
|
||||||
orm.RegisterModel(new(User))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
RegisterModel 也可以同时注册多个 model
|
|
||||||
|
|
||||||
```go
|
|
||||||
orm.RegisterModel(new(User), new(Profile), new(Post))
|
|
||||||
```
|
|
||||||
|
|
||||||
详细的 struct 定义请查看文档 [模型定义](Models.md)
|
|
||||||
|
|
||||||
#### RegisterModelWithPrefix
|
|
||||||
|
|
||||||
使用表名前缀
|
|
||||||
|
|
||||||
```go
|
|
||||||
orm.RegisterModelWithPrefix("prefix_", new(User))
|
|
||||||
```
|
|
||||||
|
|
||||||
创建后的表名为 prefix_user
|
|
||||||
|
|
||||||
## ORM 接口使用
|
|
||||||
|
|
||||||
使用 orm 必然接触的 Ormer 接口,我们来熟悉一下
|
|
||||||
|
|
||||||
```go
|
|
||||||
var o Ormer
|
|
||||||
o = orm.NewOrm() // 创建一个 Ormer
|
|
||||||
// NewOrm 的同时会执行 orm.BootStrap (整个 app 只执行一次),用以验证模型之间的定义并缓存。
|
|
||||||
```
|
|
||||||
|
|
||||||
* type Ormer interface {
|
|
||||||
* [Read(Modeler) error](Object.md#read)
|
|
||||||
* [Insert(Modeler) (int64, error)](Object.md#insert)
|
|
||||||
* [Update(Modeler) (int64, error)](Object.md#update)
|
|
||||||
* [Delete(Modeler) (int64, error)](Object.md#delete)
|
|
||||||
* [M2mAdd(Modeler, string, ...interface{}) (int64, error)](Object.md#m2madd)
|
|
||||||
* [M2mDel(Modeler, string, ...interface{}) (int64, error)](Object.md#m2mdel)
|
|
||||||
* [LoadRel(Modeler, string) (int64, error)](Object.md#loadRel)
|
|
||||||
* [QueryTable(interface{}) QuerySeter](#querytable)
|
|
||||||
* [Using(string) error](#using)
|
|
||||||
* [Begin() error](Transaction.md)
|
|
||||||
* [Commit() error](Transaction.md)
|
|
||||||
* [Rollback() error](Transaction.md)
|
|
||||||
* [Raw(string, ...interface{}) RawSeter](#raw)
|
|
||||||
* [Driver() Driver](#driver)
|
|
||||||
* }
|
|
||||||
|
|
||||||
|
|
||||||
#### QueryTable
|
|
||||||
|
|
||||||
传入表名,或者 Modeler 对象,返回一个 [QuerySeter](Query.md#queryseter)
|
|
||||||
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
var qs QuerySeter
|
|
||||||
qs = o.QueryTable("user")
|
|
||||||
// 如果表没有定义过,会立刻 panic
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Using
|
|
||||||
|
|
||||||
切换为其他数据库
|
|
||||||
|
|
||||||
```go
|
|
||||||
orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8", 30)
|
|
||||||
orm.RegisterDataBase("db2", "sqlite3", "data.db", 30)
|
|
||||||
|
|
||||||
o1 := orm.NewOrm()
|
|
||||||
o1.Using("db1")
|
|
||||||
|
|
||||||
o2 := orm.NewOrm()
|
|
||||||
o2.Using("db2")
|
|
||||||
|
|
||||||
// 切换为其他数据库以后
|
|
||||||
// 这个 Ormer 对象的其下的 api 调用都将使用这个数据库
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
默认使用 `default` 数据库,无需调用 Using
|
|
||||||
|
|
||||||
#### Raw
|
|
||||||
|
|
||||||
使用 sql 语句直接进行操作
|
|
||||||
|
|
||||||
Raw 函数,返回一个 [RawSeter](Raw.md) 用以对设置的 sql 语句和参数进行操作
|
|
||||||
|
|
||||||
```go
|
|
||||||
o := NewOrm()
|
|
||||||
var r RawSeter
|
|
||||||
r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Driver
|
|
||||||
|
|
||||||
返回当前 orm 使用的 db 信息
|
|
||||||
|
|
||||||
```go
|
|
||||||
type Driver interface {
|
|
||||||
Name() string
|
|
||||||
Type() DriverType
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
orm.RegisterDataBase("db1", "mysql", "root:root@/orm_db2?charset=utf8", 30)
|
|
||||||
orm.RegisterDataBase("db2", "sqlite3", "data.db", 30)
|
|
||||||
|
|
||||||
o1 := orm.NewOrm()
|
|
||||||
o1.Using("db1")
|
|
||||||
dr := o1.Driver()
|
|
||||||
fmt.Println(dr.Name() == "db1") // true
|
|
||||||
fmt.Println(dr.Type() == orm.DR_MySQL) // true
|
|
||||||
|
|
||||||
o2 := orm.NewOrm()
|
|
||||||
o2.Using("db2")
|
|
||||||
dr = o2.Driver()
|
|
||||||
fmt.Println(dr.Name() == "db2") // true
|
|
||||||
fmt.Println(dr.Type() == orm.DR_Sqlite) // true
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## 调试模式打印查询语句
|
|
||||||
|
|
||||||
简单的设置 Debug 为 true 打印查询的语句
|
|
||||||
|
|
||||||
可能存在性能问题,不建议使用在产品模式
|
|
||||||
|
|
||||||
```go
|
|
||||||
func main() {
|
|
||||||
orm.Debug = true
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
默认使用 os.Stderr 输出日志信息
|
|
||||||
|
|
||||||
改变输出到你自己的 io.Writer
|
|
||||||
|
|
||||||
```go
|
|
||||||
var w io.Writer
|
|
||||||
...
|
|
||||||
// 设置为你的 io.Writer
|
|
||||||
...
|
|
||||||
orm.DebugLog = orm.NewLog(w)
|
|
||||||
```
|
|
||||||
|
|
||||||
日志格式
|
|
||||||
|
|
||||||
```go
|
|
||||||
[ORM] - 时间 - [Queries/数据库名] - [执行操作/执行时间] - [SQL语句] - 使用标点 `,` 分隔的参数列表 - 打印遇到的错误
|
|
||||||
```
|
|
||||||
|
|
||||||
```go
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `user` (`name`) VALUES (?)] - `slene`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.5ms] - [UPDATE `user` SET `name` = ? WHERE `id` = ?] - `astaxie`, `14`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [db.QueryRow / 0.4ms] - [SELECT `id`, `name` FROM `user` WHERE `id` = ?] - `14`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [INSERT INTO `post` (`user_id`,`title`,`content`) VALUES (?, ?, ?)] - `14`, `beego orm`, `powerful amazing`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Query / 0.4ms] - [SELECT T1.`name` `User__Name`, T0.`user_id` `User`, T1.`id` `User__Id` FROM `post` T0 INNER JOIN `user` T1 ON T1.`id` = T0.`user_id` WHERE T0.`id` = ? LIMIT 1000] - `68`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [DELETE FROM `user` WHERE `id` = ?] - `14`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Query / 0.3ms] - [SELECT T0.`id` FROM `post` T0 WHERE T0.`user_id` IN (?) ] - `14`
|
|
||||||
[ORM] - 2013-08-09 13:18:16 - [Queries/default] - [ db.Exec / 0.4ms] - [DELETE FROM `post` WHERE `id` IN (?)] - `68`
|
|
||||||
```
|
|
||||||
|
|
||||||
日志内容包括 **所有的数据库操作**,事务,Prepare,等
|
|
@ -1,411 +0,0 @@
|
|||||||
## 高级查询
|
|
||||||
|
|
||||||
orm 以 **QuerySeter** 来组织查询,每个返回 **QuerySeter** 的方法都会获得一个新的 **QuerySeter** 对象。
|
|
||||||
|
|
||||||
基本使用方法:
|
|
||||||
```go
|
|
||||||
o := orm.NewOrm()
|
|
||||||
|
|
||||||
// 获取 QuerySeter 对象,user 为表名
|
|
||||||
qs := o.QueryTable("user")
|
|
||||||
|
|
||||||
// 也可以直接使用对象作为表名
|
|
||||||
user := new(User)
|
|
||||||
qs = o.QueryTable(user) // 返回 QuerySeter
|
|
||||||
```
|
|
||||||
## expr
|
|
||||||
|
|
||||||
QuerySeter 中用于描述字段和 sql 操作符,使用简单的 expr 查询方法
|
|
||||||
|
|
||||||
字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用 `Profile__Age` 注意,字段的分隔符号使用双下划线 `__`,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如 `Profile__Age__gt` 代表 Profile.Age > 18 的条件查询。
|
|
||||||
|
|
||||||
注释后面将描述对应的 sql 语句,仅仅是描述 expr 的类似结果,并不代表实际生成的语句。
|
|
||||||
```go
|
|
||||||
qs.Filter("id", 1) // WHERE id = 1
|
|
||||||
qs.Filter("profile__age", 18) // WHERE profile.age = 18
|
|
||||||
qs.Filter("Profile__Age", 18) // 使用字段名和Field名都是允许的
|
|
||||||
qs.Filter("profile__age", 18) // WHERE profile.age = 18
|
|
||||||
qs.Filter("profile__age__gt", 18) // WHERE profile.age > 18
|
|
||||||
qs.Filter("profile__age__gte", 18) // WHERE profile.age >= 18
|
|
||||||
qs.Filter("profile__age__in", 18, 20) // WHERE profile.age IN (18, 20)
|
|
||||||
|
|
||||||
qs.Filter("profile__age__in", 18, 20).Exclude("profile__lt", 1000)
|
|
||||||
// WHERE profile.age IN (18, 20) AND NOT profile_id < 1000
|
|
||||||
```
|
|
||||||
## Operators
|
|
||||||
|
|
||||||
当前支持的操作符号:
|
|
||||||
|
|
||||||
* [exact](#exact) / [iexact](#iexact) 等于
|
|
||||||
* [contains](#contains) / [icontains](#icontains) 包含
|
|
||||||
* [gt / gte](#gt / gte) 大于 / 大于等于
|
|
||||||
* [lt / lte](#lt / lte) 小于 / 小于等于
|
|
||||||
* [startswith](#startswith) / [istartswith](#istartswith) 以...起始
|
|
||||||
* [endswith](#endswith) / [iendswith](#iendswith) 以...结束
|
|
||||||
* [in](#in)
|
|
||||||
* [isnull](#isnull)
|
|
||||||
|
|
||||||
后面以 `i` 开头的表示:大小写不敏感
|
|
||||||
|
|
||||||
#### exact
|
|
||||||
|
|
||||||
Filter / Exclude / Condition expr 的默认值
|
|
||||||
```go
|
|
||||||
qs.Filter("name", "slene") // WHERE name = 'slene'
|
|
||||||
qs.Filter("name__exact", "slene") // WHERE name = 'slene'
|
|
||||||
// 使用 = 匹配,大小写是否敏感取决于数据表使用的 collation
|
|
||||||
qs.Filter("profile", nil) // WHERE profile_id IS NULL
|
|
||||||
```
|
|
||||||
#### iexact
|
|
||||||
```go
|
|
||||||
qs.Filter("name__iexact", "slene")
|
|
||||||
// WHERE name LIKE 'slene'
|
|
||||||
// 大小写不敏感,匹配任意 'Slene' 'sLENE'
|
|
||||||
```
|
|
||||||
#### contains
|
|
||||||
```go
|
|
||||||
qs.Filter("name__contains", "slene")
|
|
||||||
// WHERE name LIKE BINARY '%slene%'
|
|
||||||
// 大小写敏感, 匹配包含 slene 的字符
|
|
||||||
```
|
|
||||||
#### icontains
|
|
||||||
```go
|
|
||||||
qs.Filter("name__icontains", "slene")
|
|
||||||
// WHERE name LIKE '%slene%'
|
|
||||||
// 大小写不敏感, 匹配任意 'im Slene', 'im sLENE'
|
|
||||||
```
|
|
||||||
#### in
|
|
||||||
```go
|
|
||||||
qs.Filter("profile__age__in", 17, 18, 19, 20)
|
|
||||||
// WHERE profile.age IN (17, 18, 19, 20)
|
|
||||||
```
|
|
||||||
#### gt / gte
|
|
||||||
```go
|
|
||||||
qs.Filter("profile__age__gt", 17)
|
|
||||||
// WHERE profile.age > 17
|
|
||||||
|
|
||||||
qs.Filter("profile__age__gte", 18)
|
|
||||||
// WHERE profile.age >= 18
|
|
||||||
```
|
|
||||||
#### lt / lte
|
|
||||||
```go
|
|
||||||
qs.Filter("profile__age__lt", 17)
|
|
||||||
// WHERE profile.age < 17
|
|
||||||
|
|
||||||
qs.Filter("profile__age__lte", 18)
|
|
||||||
// WHERE profile.age <= 18
|
|
||||||
```
|
|
||||||
#### startswith
|
|
||||||
```go
|
|
||||||
qs.Filter("name__startswith", "slene")
|
|
||||||
// WHERE name LIKE BINARY 'slene%'
|
|
||||||
// 大小写敏感, 匹配以 'slene' 起始的字符串
|
|
||||||
```
|
|
||||||
#### istartswith
|
|
||||||
```go
|
|
||||||
qs.Filter("name__istartswith", "slene")
|
|
||||||
// WHERE name LIKE 'slene%'
|
|
||||||
// 大小写不敏感, 匹配任意以 'slene', 'Slene' 起始的字符串
|
|
||||||
```
|
|
||||||
#### endswith
|
|
||||||
```go
|
|
||||||
qs.Filter("name__endswith", "slene")
|
|
||||||
// WHERE name LIKE BINARY '%slene'
|
|
||||||
// 大小写敏感, 匹配以 'slene' 结束的字符串
|
|
||||||
```
|
|
||||||
#### iendswith
|
|
||||||
```go
|
|
||||||
qs.Filter("name__startswith", "slene")
|
|
||||||
// WHERE name LIKE '%slene'
|
|
||||||
// 大小写不敏感, 匹配任意以 'slene', 'Slene' 结束的字符串
|
|
||||||
```
|
|
||||||
#### isnull
|
|
||||||
```go
|
|
||||||
qs.Filter("profile__isnull", true)
|
|
||||||
qs.Filter("profile_id__isnull", true)
|
|
||||||
// WHERE profile_id IS NULL
|
|
||||||
|
|
||||||
qs.Filter("profile__isnull", false)
|
|
||||||
// WHERE profile_id IS NOT NULL
|
|
||||||
```
|
|
||||||
## 高级查询接口使用
|
|
||||||
|
|
||||||
QuerySeter 是高级查询使用的接口,我们来熟悉下他的接口方法
|
|
||||||
|
|
||||||
* type QuerySeter interface {
|
|
||||||
* [Filter(string, ...interface{}) QuerySeter](#filter)
|
|
||||||
* [Exclude(string, ...interface{}) QuerySeter](#exclude)
|
|
||||||
* [SetCond(*Condition) QuerySeter](#setcond)
|
|
||||||
* [Limit(int, ...int64) QuerySeter](#limit)
|
|
||||||
* [Offset(int64) QuerySeter](#offset)
|
|
||||||
* [OrderBy(...string) QuerySeter](#orderby)
|
|
||||||
* [RelatedSel(...interface{}) QuerySeter](#relatedsel)
|
|
||||||
* [Count() (int64, error)](#count)
|
|
||||||
* [Update(Params) (int64, error)](#update)
|
|
||||||
* [Delete() (int64, error)](#delete)
|
|
||||||
* [PrepareInsert() (Inserter, error)](#prepareinsert)
|
|
||||||
* [All(interface{}) (int64, error)](#all)
|
|
||||||
* [One(Modeler) error](#one)
|
|
||||||
* [Values(*[]Params, ...string) (int64, error)](#values)
|
|
||||||
* [ValuesList(*[]ParamsList, ...string) (int64, error)](#valueslist)
|
|
||||||
* [ValuesFlat(*ParamsList, string) (int64, error)](#valuesflat)
|
|
||||||
* }
|
|
||||||
|
|
||||||
* 每个返回 QuerySeter 的 api 调用时都会新建一个 QuerySeter,不影响之前创建的。
|
|
||||||
|
|
||||||
* 高级查询使用 Filter 和 Exclude 来做常用的条件查询。囊括两种清晰的过滤规则:包含, 排除
|
|
||||||
|
|
||||||
#### Filter
|
|
||||||
|
|
||||||
用来过滤查询结果,起到 **包含条件** 的作用
|
|
||||||
|
|
||||||
多个 Filter 之间使用 `AND` 连接
|
|
||||||
```go
|
|
||||||
qs.Filter("profile__isnull", true).Filter("name", "slene")
|
|
||||||
// WHERE profile_id IS NULL AND name = 'slene'
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Exclude
|
|
||||||
|
|
||||||
用来过滤查询结果,起到 **排除条件** 的作用
|
|
||||||
|
|
||||||
使用 `NOT` 排除条件
|
|
||||||
|
|
||||||
多个 Exclude 之间使用 `AND` 连接
|
|
||||||
```go
|
|
||||||
qs.Exclude("profile__isnull", true).Filter("name", "slene")
|
|
||||||
// WHERE NOT profile_id IS NULL AND name = 'slene'
|
|
||||||
```
|
|
||||||
|
|
||||||
#### SetCond
|
|
||||||
|
|
||||||
自定义条件表达式
|
|
||||||
|
|
||||||
```go
|
|
||||||
cond := NewCondition()
|
|
||||||
cond1 := cond.And("profile__isnull", false).AndNot("status__in", 1).Or("profile__age__gt", 2000)
|
|
||||||
|
|
||||||
qs := orm.QueryTable("user")
|
|
||||||
qs = qs.SetCond(cond1)
|
|
||||||
// WHERE ... AND ... AND NOT ... OR ...
|
|
||||||
|
|
||||||
cond2 := cond.AndCond(cond1).OrCond(cond.And("name", "slene"))
|
|
||||||
qs = qs.SetCond(cond2).Count()
|
|
||||||
// WHERE (... AND ... AND NOT ... OR ...) OR ( ... )
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Limit
|
|
||||||
|
|
||||||
限制最大返回数据行数,第二个参数可以设置 `Offset`
|
|
||||||
```go
|
|
||||||
var DefaultRowsLimit = 1000 // orm 默认的 limit 值为 1000
|
|
||||||
|
|
||||||
// 默认情况下 select 查询的最大行数为 1000
|
|
||||||
// LIMIT 1000
|
|
||||||
|
|
||||||
qs.Limit(10)
|
|
||||||
// LIMIT 10
|
|
||||||
|
|
||||||
qs.Limit(10, 20)
|
|
||||||
// LIMIT 10 OFFSET 20
|
|
||||||
|
|
||||||
qs.Limit(-1)
|
|
||||||
// no limit
|
|
||||||
|
|
||||||
qs.Limit(-1, 100)
|
|
||||||
// LIMIT 18446744073709551615 OFFSET 100
|
|
||||||
// 18446744073709551615 是 1<<64 - 1 用来指定无 limit 限制 但有 offset 偏移的情况
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Offset
|
|
||||||
|
|
||||||
设置 偏移行数
|
|
||||||
```go
|
|
||||||
qs.Offset(20)
|
|
||||||
// LIMIT 1000 OFFSET 20
|
|
||||||
```
|
|
||||||
|
|
||||||
#### OrderBy
|
|
||||||
|
|
||||||
参数使用 **expr**
|
|
||||||
|
|
||||||
在 expr 前使用减号 `-` 表示 `DESC` 的排列
|
|
||||||
```go
|
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
#### RelatedSel
|
|
||||||
|
|
||||||
关系查询,参数使用 **expr**
|
|
||||||
```go
|
|
||||||
var DefaultRelsDepth = 5 // 默认情况下直接调用 RelatedSel 将进行最大 5 层的关系查询
|
|
||||||
|
|
||||||
qs := o.QueryTable("post")
|
|
||||||
|
|
||||||
qs.RelateSel()
|
|
||||||
// INNER JOIN user ... LEFT OUTER JOIN profile ...
|
|
||||||
|
|
||||||
qs.RelateSel("user")
|
|
||||||
// INNER JOIN user ...
|
|
||||||
// 设置 expr 只对设置的字段进行关系查询
|
|
||||||
|
|
||||||
// 对设置 null 属性的 Field 将使用 LEFT OUTER JOIN
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Count
|
|
||||||
依据当前的查询条件,返回结果行数
|
|
||||||
```go
|
|
||||||
cnt, err := o.QueryTable("user").Count() // SELECT COUNT(*) FROM USER
|
|
||||||
fmt.Printf("Count Num: %s, %s", cnt, err)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Update
|
|
||||||
依据当前查询条件,进行批量更新操作
|
|
||||||
```go
|
|
||||||
num, err := o.QueryTable("user").Filter("name", "slene").Update(orm.Params{
|
|
||||||
"name": "astaxie",
|
|
||||||
})
|
|
||||||
fmt.Printf("Affected Num: %s, %s", num, err)
|
|
||||||
// SET name = "astaixe" WHERE name = "slene"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Delete
|
|
||||||
依据当前查询条件,进行批量删除操作
|
|
||||||
```go
|
|
||||||
num, err := o.QueryTable("user").Filter("name", "slene").Delete()
|
|
||||||
fmt.Printf("Affected Num: %s, %s", num, err)
|
|
||||||
// DELETE FROM user WHERE name = "slene"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### PrepareInsert
|
|
||||||
|
|
||||||
用于一次 prepare 多次 insert 插入,以提高批量插入的速度。
|
|
||||||
|
|
||||||
```go
|
|
||||||
var users []*User
|
|
||||||
...
|
|
||||||
qs := o.QueryTable("user")
|
|
||||||
i, _ := qs.PrepareInsert()
|
|
||||||
for _, user := range users {
|
|
||||||
id, err := i.Insert(user)
|
|
||||||
if err != nil {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// PREPARE INSERT INTO user (`name`, ...) VALUES (?, ...)
|
|
||||||
// EXECUTE INSERT INTO user (`name`, ...) VALUES ("slene", ...)
|
|
||||||
// EXECUTE ...
|
|
||||||
// ...
|
|
||||||
i.Close() // 别忘记关闭 statement
|
|
||||||
```
|
|
||||||
|
|
||||||
#### All
|
|
||||||
返回对应的结果集对象
|
|
||||||
```go
|
|
||||||
var users []*User
|
|
||||||
num, err := o.QueryTable("user").Filter("name", "slene").All(&users)
|
|
||||||
fmt.Printf("Returned Rows Num: %s, %s", num, err)
|
|
||||||
```
|
|
||||||
|
|
||||||
#### One
|
|
||||||
|
|
||||||
尝试返回单条记录
|
|
||||||
|
|
||||||
```go
|
|
||||||
var user *User
|
|
||||||
err := o.QueryTable("user").Filter("name", "slene").One(&user)
|
|
||||||
if err == orm.ErrMultiRows {
|
|
||||||
// 多条的时候报错
|
|
||||||
fmt.Printf("Returned Multi Rows Not One")
|
|
||||||
}
|
|
||||||
if err == orm.ErrNoRows {
|
|
||||||
// 没有找到记录
|
|
||||||
fmt.Printf("Not row found")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Values
|
|
||||||
返回结果集的 key => value 值
|
|
||||||
|
|
||||||
key 为 Model 里的 Field name,value 的值 以 string 保存
|
|
||||||
|
|
||||||
```go
|
|
||||||
var maps []orm.Params
|
|
||||||
num, err := o.QueryTable("user").Values(&maps)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Result Nums: %d\n", num)
|
|
||||||
for _, m := range maps {
|
|
||||||
fmt.Println(m["Id"], m["Name"])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
返回指定的 Field 数据
|
|
||||||
|
|
||||||
**TODO**: 暂不支持级联查询 **RelatedSel** 直接返回 Values
|
|
||||||
|
|
||||||
但可以直接指定 expr 级联返回需要的数据
|
|
||||||
|
|
||||||
```go
|
|
||||||
var maps []orm.Params
|
|
||||||
num, err := o.QueryTable("user").Values(&maps, "id", "name", "profile", "profile__age")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Result Nums: %d\n", num)
|
|
||||||
for _, m := range maps {
|
|
||||||
fmt.Println(m["Id"], m["Name"], m["Profile"], m["Profile__Age"])
|
|
||||||
// map 中的数据都是展开的,没有复杂的嵌套
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### ValuesList
|
|
||||||
|
|
||||||
顾名思义,返回的结果集以slice存储
|
|
||||||
|
|
||||||
结果的排列与 Model 中定义的 Field 顺序一致
|
|
||||||
|
|
||||||
返回的每个元素值以 string 保存
|
|
||||||
|
|
||||||
```go
|
|
||||||
var lists []orm.ParamsList
|
|
||||||
num, err := o.QueryTable("user").ValuesList(&lists)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Result Nums: %d\n", num)
|
|
||||||
for _, row := range lists {
|
|
||||||
fmt.Println(row)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
当然也可以指定 expr 返回指定的 Field
|
|
||||||
|
|
||||||
```go
|
|
||||||
var lists []orm.ParamsList
|
|
||||||
num, err := o.QueryTable("user").ValuesList(&lists, "name", "profile__age")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Result Nums: %d\n", num)
|
|
||||||
for _, row := range lists {
|
|
||||||
fmt.Printf("Name: %s, Age: %s\m", row[0], row[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### ValuesFlat
|
|
||||||
|
|
||||||
只返回特定的 Field 值,讲结果集展开到单个 slice 里
|
|
||||||
|
|
||||||
```go
|
|
||||||
var list orm.ParamsList
|
|
||||||
num, err := o.QueryTable("user").ValuesFlat(&list, "name")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Result Nums: %d\n", num)
|
|
||||||
fmt.Printf("All User Names: %s", strings.Join(list, ", ")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
|||||||
最新文档请查看 beedoc
|
|
||||||
|
|
||||||
* [中文](http://beego.me/docs/Models_Overview?lang=zh)
|
|
||||||
* [English](http://beego.me/docs/Models_Overview?lang=en)
|
|
||||||
|
|
||||||
## 文档目录
|
|
||||||
|
|
||||||
1. [Orm 使用方法](Orm.md)
|
|
||||||
- [数据库的设置](Orm.md#数据库的设置)
|
|
||||||
* [驱动类型设置](Orm.md#registerdriver)
|
|
||||||
* [参数设置](Orm.md#registerdatabase)
|
|
||||||
* [时区设置](Orm.md#时区设置)
|
|
||||||
- [注册模型](Orm.md#注册模型)
|
|
||||||
- [ORM 接口使用](Orm.md#orm-接口使用)
|
|
||||||
- [调试模式打印查询语句](Orm.md#调试模式打印查询语句)
|
|
||||||
2. [对象的CRUD操作](Object.md)
|
|
||||||
3. [高级查询](Query.md)
|
|
||||||
- [使用的表达式语法](Query.md#expr)
|
|
||||||
- [支持的操作符号](Query.md#operators)
|
|
||||||
- [高级查询接口使用](Query.md#高级查询接口使用)
|
|
||||||
4. [使用SQL语句进行查询](Raw.md)
|
|
||||||
5. [事务处理](Transaction.md)
|
|
||||||
6. [模型定义](Models.md)
|
|
||||||
- [Struct Tag 设置参数](Models.md#struct-tag-设置参数)
|
|
||||||
- [表关系设置](Models.md#表关系设置)
|
|
||||||
- [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应)
|
|
||||||
7. [命令模式](Cmd.md)
|
|
||||||
- [自动建表](Cmd.md#自动建表)
|
|
||||||
- [打印建表SQL](Cmd.md#打印建表sql)
|
|
||||||
8. [Test ORM](Test.md)
|
|
||||||
9. Custom Fields
|
|
||||||
10. Faq
|
|
||||||
|
|
||||||
|
|
||||||
### 文档更新记录
|
|
||||||
|
|
||||||
* 2013-08-20: 这里不再更新,最新文档在 beedoc, [中文](http://beego.me/docs/Models_Overview?lang=zh) / [English](http://beego.me/docs/Models_Overview?lang=en)
|
|
||||||
* 2013-08-19: 增加[自动建表](Cmd.md#自动建表)功能
|
|
||||||
* 2013-08-13: ORM 的 [时区设置](Orm.md#时区设置)
|
|
||||||
* 2013-08-13: [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应) 推荐的数据库对应使用的类型
|
|
@ -1,116 +0,0 @@
|
|||||||
## 使用SQL语句进行查询
|
|
||||||
|
|
||||||
* 使用 Raw SQL 查询,无需使用 ORM 表定义
|
|
||||||
* 多数据库,都可直接使用占位符号 `?`,自动转换
|
|
||||||
* 查询时的参数,支持使用 Model Struct 和 Slice, Array
|
|
||||||
|
|
||||||
```go
|
|
||||||
ids := []int{1, 2, 3}
|
|
||||||
p.Raw("SELECT name FROM user WHERE id IN (?, ?, ?)", ids)
|
|
||||||
```
|
|
||||||
|
|
||||||
创建一个 **RawSeter**
|
|
||||||
|
|
||||||
```go
|
|
||||||
o := NewOrm()
|
|
||||||
var r RawSeter
|
|
||||||
r = o.Raw("UPDATE user SET name = ? WHERE name = ?", "testing", "slene")
|
|
||||||
```
|
|
||||||
|
|
||||||
* type RawSeter interface {
|
|
||||||
* [Exec() (int64, error)](#exec)
|
|
||||||
* [QueryRow(...interface{}) error](#queryrow)
|
|
||||||
* [QueryRows(...interface{}) (int64, error)](#queryrows)
|
|
||||||
* [SetArgs(...interface{}) RawSeter](#setargs)
|
|
||||||
* [Values(*[]Params) (int64, error)](#values)
|
|
||||||
* [ValuesList(*[]ParamsList) (int64, error)](#valueslist)
|
|
||||||
* [ValuesFlat(*ParamsList) (int64, error)](#valuesflat)
|
|
||||||
* [Prepare() (RawPreparer, error)](#prepare)
|
|
||||||
* }
|
|
||||||
|
|
||||||
#### Exec
|
|
||||||
|
|
||||||
执行sql语句
|
|
||||||
|
|
||||||
```go
|
|
||||||
num, err := r.Exec()
|
|
||||||
```
|
|
||||||
|
|
||||||
#### QueryRow
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
#### QueryRows
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
#### SetArgs
|
|
||||||
|
|
||||||
改变 Raw(sql, args...) 中的 args 参数,返回一个新的 RawSeter
|
|
||||||
|
|
||||||
用于单条 sql 语句,重复利用,替换参数然后执行。
|
|
||||||
|
|
||||||
```go
|
|
||||||
num, err := r.SetArgs("arg1", "arg2").Exec()
|
|
||||||
num, err := r.SetArgs("arg1", "arg2").Exec()
|
|
||||||
...
|
|
||||||
```
|
|
||||||
#### Values / ValuesList / ValuesFlat
|
|
||||||
|
|
||||||
Raw SQL 查询获得的结果集 Value 为 `string` 类型,NULL 字段的值为空 ``
|
|
||||||
|
|
||||||
#### Values
|
|
||||||
|
|
||||||
|
|
||||||
返回结果集的 key => value 值
|
|
||||||
|
|
||||||
```go
|
|
||||||
var maps []orm.Params
|
|
||||||
num, err = o.Raw("SELECT user_name FROM user WHERE status = ?", 1).Values(&maps)
|
|
||||||
if err == nil && num > 0 {
|
|
||||||
fmt.Println(maps[0]["user_name"]) // slene
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### ValuesList
|
|
||||||
|
|
||||||
返回结果集 slice
|
|
||||||
|
|
||||||
```go
|
|
||||||
var lists []orm.ParamsList
|
|
||||||
num, err = o.Raw("SELECT user_name FROM user WHERE status = ?", 1).ValuesList(&lists)
|
|
||||||
if err == nil && num > 0 {
|
|
||||||
fmt.Println(lists[0][0]) // slene
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### ValuesFlat
|
|
||||||
|
|
||||||
返回单一字段的平铺 slice 数据
|
|
||||||
|
|
||||||
```go
|
|
||||||
var list orm.ParamsList
|
|
||||||
num, err = o.Raw("SELECT id FROM user WHERE id < ?", 10).ValuesList(&list)
|
|
||||||
if err == nil && num > 0 {
|
|
||||||
fmt.Println(list) // []{"1","2","3",...}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Prepare
|
|
||||||
|
|
||||||
用于一次 prepare 多次 exec,以提高批量执行的速度。
|
|
||||||
|
|
||||||
```go
|
|
||||||
p, err := o.Raw("UPDATE user SET name = ? WHERE name = ?").Prepare()
|
|
||||||
num, err := p.Exec("testing", "slene")
|
|
||||||
num, err = p.Exec("testing", "astaxie")
|
|
||||||
...
|
|
||||||
...
|
|
||||||
p.Close() // 别忘记关闭 statement
|
|
||||||
```
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
1. 我的 app 需要支持多类型数据库,如何在使用 Raw SQL 的时候判断当前使用的数据库类型。
|
|
||||||
|
|
||||||
使用 Ormer 的 [Driver方法](Orm.md#driver) 可以进行判断
|
|
@ -1,34 +0,0 @@
|
|||||||
## Test ORM
|
|
||||||
|
|
||||||
测试代码参见
|
|
||||||
|
|
||||||
```bash
|
|
||||||
models_test.go // 表定义
|
|
||||||
orm_test.go // 测试用例
|
|
||||||
```
|
|
||||||
|
|
||||||
#### MySQL
|
|
||||||
```bash
|
|
||||||
mysql -u root -e 'create database orm_test;'
|
|
||||||
export ORM_DRIVER=mysql
|
|
||||||
export ORM_SOURCE="root:@/orm_test?charset=utf8"
|
|
||||||
go test -v github.com/astaxie/beego/orm
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### Sqlite3
|
|
||||||
```bash
|
|
||||||
touch /path/to/orm_test.db
|
|
||||||
export ORM_DRIVER=sqlite3
|
|
||||||
export ORM_SOURCE=/path/to/orm_test.db
|
|
||||||
go test -v github.com/astaxie/beego/orm
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
#### PostgreSQL
|
|
||||||
```bash
|
|
||||||
psql -c 'create database orm_test;' -U postgres
|
|
||||||
export ORM_DRIVER=postgres
|
|
||||||
export ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable"
|
|
||||||
go test -v github.com/astaxie/beego/orm
|
|
||||||
```
|
|
@ -1,17 +0,0 @@
|
|||||||
## 事务处理
|
|
||||||
|
|
||||||
orm 可以简单的进行事务操作
|
|
||||||
|
|
||||||
```go
|
|
||||||
o := NewOrm()
|
|
||||||
err := o.Begin()
|
|
||||||
// 事务处理过程
|
|
||||||
...
|
|
||||||
...
|
|
||||||
// 此过程中的所有使用 o Ormer 对象的查询都在事务处理范围内
|
|
||||||
if SomeError {
|
|
||||||
err = o.Rollback()
|
|
||||||
} else {
|
|
||||||
err = o.Commit()
|
|
||||||
}
|
|
||||||
```
|
|
Loading…
Reference in New Issue
Block a user