diff --git a/orm/docs/zh/Cmd.md b/orm/docs/zh/Cmd.md deleted file mode 100644 index 932cb1c6..00000000 --- a/orm/docs/zh/Cmd.md +++ /dev/null @@ -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 的数据库 diff --git a/orm/docs/zh/CustomFields.md b/orm/docs/zh/CustomFields.md deleted file mode 100644 index 3a3c835c..00000000 --- a/orm/docs/zh/CustomFields.md +++ /dev/null @@ -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 \ No newline at end of file diff --git a/orm/docs/zh/Models.md b/orm/docs/zh/Models.md deleted file mode 100644 index c8263822..00000000 --- a/orm/docs/zh/Models.md +++ /dev/null @@ -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 \ No newline at end of file diff --git a/orm/docs/zh/Models.sql b/orm/docs/zh/Models.sql deleted file mode 100644 index 2d9d5ce0..00000000 --- a/orm/docs/zh/Models.sql +++ /dev/null @@ -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; diff --git a/orm/docs/zh/Object.md b/orm/docs/zh/Object.md deleted file mode 100644 index f1a2e0e1..00000000 --- a/orm/docs/zh/Object.md +++ /dev/null @@ -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 的值 diff --git a/orm/docs/zh/Orm.md b/orm/docs/zh/Orm.md deleted file mode 100644 index 6d3b6b06..00000000 --- a/orm/docs/zh/Orm.md +++ /dev/null @@ -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,等 diff --git a/orm/docs/zh/Query.md b/orm/docs/zh/Query.md deleted file mode 100644 index cfc4073c..00000000 --- a/orm/docs/zh/Query.md +++ /dev/null @@ -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, ", ") -} -``` - - - diff --git a/orm/docs/zh/README.md b/orm/docs/zh/README.md deleted file mode 100644 index e01c8cad..00000000 --- a/orm/docs/zh/README.md +++ /dev/null @@ -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#模型字段与数据库类型的对应) 推荐的数据库对应使用的类型 diff --git a/orm/docs/zh/Raw.md b/orm/docs/zh/Raw.md deleted file mode 100644 index 0d571edf..00000000 --- a/orm/docs/zh/Raw.md +++ /dev/null @@ -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) 可以进行判断 diff --git a/orm/docs/zh/Test.md b/orm/docs/zh/Test.md deleted file mode 100644 index c2146336..00000000 --- a/orm/docs/zh/Test.md +++ /dev/null @@ -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 -``` \ No newline at end of file diff --git a/orm/docs/zh/Transaction.md b/orm/docs/zh/Transaction.md deleted file mode 100644 index 51172c09..00000000 --- a/orm/docs/zh/Transaction.md +++ /dev/null @@ -1,17 +0,0 @@ -## 事务处理 - -orm 可以简单的进行事务操作 - -```go -o := NewOrm() -err := o.Begin() -// 事务处理过程 -... -... -// 此过程中的所有使用 o Ormer 对象的查询都在事务处理范围内 -if SomeError { - err = o.Rollback() -} else { - err = o.Commit() -} -```