Skip to content
This repository has been archived by the owner on Jul 11, 2019. It is now read-only.

Commit

Permalink
docs improved
Browse files Browse the repository at this point in the history
  • Loading branch information
lunny committed Dec 31, 2013
1 parent d1a0338 commit 44a82b0
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 31 deletions.
1 change: 1 addition & 0 deletions benchmark.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
go test -v -bench=. -run=XXX
101 changes: 70 additions & 31 deletions docs/QuickStart.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ xorm 快速入门

* [1.创建Orm引擎](#10)
* [2.定义表结构体](#20)
* [2.1.名称映射规则](#21)
* [2.2.使用Table和Tag改变名称映射](#22)
* [2.3.Column属性定义](#23)
* [2.4.Go与字段类型对应表](#24)
* [2.1.名称映射规则](#21)
* [2.2.前缀映射规则和后缀映射规则](#22)
* [2.3.使用Table和Tag改变名称映射](#23)
* [2.4.Column属性定义](#24)
* [2.5.Go与字段类型对应表](#25)
* [3.表结构操作](#30)
* [3.1 获取数据库信息](#31)
* [3.2 表操作](#32)
Expand All @@ -19,7 +20,8 @@ xorm 快速入门
* [5.3.Get方法](#63)
* [5.4.Find方法](#64)
* [5.5.Iterate方法](#65)
* [5.6.Count方法](#66)
* [5.6.Count方法](#66)
* [5.7.Rows方法](#67)
* [6.更新数据](#70)
* [6.1.乐观锁](#71)
* [7.删除数据](#80)
Expand Down Expand Up @@ -69,13 +71,15 @@ xorm当前支持四种驱动如下:

* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)

* Postgres: [github.com/lib/pq](https://github.com/lib/pq)
* Postgres: [github.com/lib/pq](https://github.com/lib/pq)

* MsSql: [github.com/lunny/godbc](https://githubcom/lunny/godbc)

NewEngine传入的参数和`sql.Open`传入的参数完全相同,因此,使用哪个驱动前,请查看此驱动中关于传入参数的说明文档。

在engine创建完成后可以进行一些设置,如:

1.设置
1.错误显示设置,默认如下均为`false`

* `engine.ShowSQL = true`,则会在控制台打印出生成的SQL语句;
* `engine.ShowDebug = true`,则会在控制台打印调试信息;
Expand All @@ -93,7 +97,7 @@ f, err := os.Create("sql.log")
engine.Logger = f
```

3.engine内部支持连接池接口,默认使用的Go所实现的连接池,同时自带了另外两种实现:一种是不使用连接池,另一种为一个自实现的连接池。推荐使用Go所实现的连接池。如果要使用自己实现的连接池,可以实现`xorm.IConnectPool`并通过`engine.SetPool`进行设置。
3.engine内部支持连接池接口,默认使用的Go所实现的连接池,同时自带了另外两种实现:一种是不使用连接池,另一种为一个自实现的连接池。推荐使用Go所实现的连接池。如果要使用自己实现的连接池,可以实现`xorm.IConnectPool`并通过`engine.SetPool`进行设置。推荐使用Go默认的连接池。

* 如果需要设置连接池的空闲数大小,可以使用`engine.SetIdleConns()`来实现。
* 如果需要设置最大打开连接数,则可以使用`engine.SetMaxConns()`来实现。
Expand All @@ -111,20 +115,33 @@ xorm支持将一个struct映射为数据库中对应的一张表。映射规则
当前SnakeMapper为默认值,如果需要改变时,在engine创建完成后使用

```Go
engine.Mapper = SameMapper{}
engine.SetMapper(SameMapper{})
```

当然,如果你使用了别的命名规则映射方案,也可以自己实现一个IMapper。
同时需要注意的是:

* 如果你使用了别的命名规则映射方案,也可以自己实现一个IMapper。
* 表名称和字段名称的映射规则默认是相同的,当然也可以设置为不同,如:
```Go
engine.SetTableMapper(SameMapper{})
engine.SetColumnMapper(SnakeMapper{})
```

<a name="22" id="22"></a>
### 2.2.使用Table和Tag改变名称映射
### 2.2.前缀映射规则和后缀映射规则

* 通过`engine.NewPrefixMapper(SnakeMapper{}, "prefix")`可以在SnakeMapper的基础上在命名中添加统一的前缀;
* 通过`engine.NewSufffixMapper(SnakeMapper{}, "prefix")`可以在SnakeMapper的基础上在命名中添加统一的后缀。

<a name="23" id="23"></a>
### 2.3.使用Table和Tag改变名称映射

如果所有的命名都是按照IMapper的映射来操作的,那当然是最理想的。但是如果碰到某个表名或者某个字段名跟映射规则不匹配时,我们就需要别的机制来改变。

通过`engine.Table()`方法可以改变struct对应的数据库表的名称,通过sturct中field对应的Tag中使用`xorm:"'column_name'"`可以使该field对应的Column名称为指定名称。这里使用两个单引号将Column名称括起来是为了防止名称冲突,因为我们在Tag中还可以对这个Column进行更多的定义。如果名称不冲突的情况,单引号也可以不使用。

<a name="23" id="23"></a>
### 2.3.Column属性定义
### 2.4.Column属性定义
我们在field对应的Tag中对Column的一些属性进行定义,定义的方法基本和我们写SQL定义表结构类似,比如:

```
Expand All @@ -140,10 +157,10 @@ type User struct {

<table>
<tr>
<td>name</td><td>当前field对应的字段的名称,可选,如不写,则自动根据field名字和转换规则命名</td>
<td>name</td><td>当前field对应的字段的名称,可选,如不写,则自动根据field名字和转换规则命名,如与其它关键字冲突,请使用单引号括起来。</td>
</tr>
<tr>
<td>pk</td><td>是否是Primary Key,如果在一个struct中有两个字段都使用了此标记,则这两个字段构成了复合主键</td>
<td>pk</td><td>是否是Primary Key,如果在一个struct中有两个字段都使用了此标记,则这两个字段构成了复合主键,单主键当前支持int32,int,int64,uint32,uint,uint64,string这7中Go的数据类型。</td>
</tr>
<tr>
<td>当前支持30多种字段类型,详情参见 [字段类型](https://github.com/lunny/xorm/blob/master/docs/COLUMNTYPE.md)</td><td>字段类型</td>
Expand All @@ -152,7 +169,7 @@ type User struct {
<td>autoincr</td><td>是否是自增</td>
</tr>
<tr>
<td>[not ]null</td><td>是否可以为空</td>
<td>[not ]null 或 notnull</td><td>是否可以为空</td>
</tr>
<tr>
<td>unique或unique(uniquename)</td><td>是否是唯一,如不加括号则该字段不允许重复;如加上括号,则括号中为联合唯一索引的名字,此时如果有另外一个或多个字段和本unique的uniquename相同,则这些uniquename相同的字段组成联合唯一索引</td>
Expand Down Expand Up @@ -188,11 +205,11 @@ type User struct {

另外有如下几条自动映射的规则:

- 1.如果field名称为`Id`而且类型为`int64`的话,会被xorm视为主键,并且拥有自增属性。如果想用`Id`以外的名字做为主键名,可以在对应的Tag上加上`xorm:"pk"`来定义主键。
- 1.如果field名称为`Id`而且类型为`int64`的话,会被xorm视为主键,并且拥有自增属性。如果想用`Id`以外的名字或非int64类型做为主键名,必须在对应的Tag上加上`xorm:"pk"`来定义主键,加上`xorm:"autoincr"`作为自增。这里需要注意的是,有些数据库并不允许非主键的自增属性

- 2.string类型默认映射为varchar(255),如果需要不同的定义,可以在tag中自定义

- 3.支持`type MyString string`等自定义的field,支持Slice, Map等field成员,这些成员默认存储为Text类型,并且默认将使用Json格式来序列化和反序列化。也支持数据库字段类型为Blob类型,如果是Blob类型,则先使用Json格式序列化再转成[]byte格式。当然[]byte或者[]uint8默认为Blob类型并且都以二进制方式存储。
- 3.支持`type MyString string`等自定义的field,支持Slice, Map等field成员,这些成员默认存储为Text类型,并且默认将使用Json格式来序列化和反序列化。也支持数据库字段类型为Blob类型,如果是Blob类型,则先使用Json格式序列化再转成[]byte格式。当然[]byte或者[]uint8默认为Blob类型并且都以二进制方式存储。具体参见 [go类型<->数据库类型对应表](https://github.com/lunny/xorm/blob/master/docs/AutoMap.md)

- 4.实现了Conversion接口的类型或者结构体,将根据接口的转换方式在类型和数据库记录之间进行相互转换。
```Go
Expand All @@ -218,7 +235,7 @@ xorm提供了一些动态获取和修改表结构的方法。对于一般的应
## 3.1 获取数据库信息

* DBMetas()
xorm支持获取表结构信息,通过调用`engine.DBMetas()`可以获取到所有的表的信息
xorm支持获取表结构信息,通过调用`engine.DBMetas()`可以获取到所有的表,字段,索引的信息。

<a name="31" id="31"></a>
## 3.2.表操作
Expand Down Expand Up @@ -270,7 +287,7 @@ user.Name = "myname"
affected, err := engine.Insert(user)
```

在插入成功后,如果该结构体有PK字段,则PK字段会被自动赋值为数据库中的id
在插入单条数据成功后,如果该结构体有自增字段,则自增字段会被自动赋值为数据库中的id
```Go
fmt.Println(user.Id)
```
Expand Down Expand Up @@ -321,22 +338,24 @@ questions[0].Content = "whywhywhwy?"
affected, err := engine.Insert(user, &questions)
```

注意:这里虽然支持同时插入,但这些插入并没有事务关系。因此有可能在中间插入出错后,后面的插入将不会继续。
这里需要注意以下几点:
* 这里虽然支持同时插入,但这些插入并没有事务关系。因此有可能在中间插入出错后,后面的插入将不会继续。
* 多条插入会自动生成`Insert into table values (),(),()`的语句,因此这样的语句有一个最大的记录数,根据经验测算在150条左右。大于150条后,生成的sql语句将太长可能导致执行失败。因此在插入大量数据时,目前需要自行分割成每150条插入一次。

<a name="60" id="60"></a>
## 5.查询和统计数据

所有的查询条件不区分调用顺序,但必须在调用Get,Find,Count这三个函数之前调用。同时需要注意的一点是,在调用的参数中,所有的字符字段名均为映射后的数据库的字段名,而不是field的名字。
所有的查询条件不区分调用顺序,但必须在调用Get,Find,Count, Iterate, Rows这几个函数之前调用。同时需要注意的一点是,在调用的参数中,如果采用默认的`SnakeMapper`所有的字符字段名均为映射后的数据库的字段名,而不是field的名字。

<a name="61" id="61"></a>
### 5.1.查询条件方法

查询和统计主要使用`Get`, `Find`, `Count`三个方法。在进行查询时可以使用多个方法来形成查询条件,条件函数如下:
查询和统计主要使用`Get`, `Find`, `Count`, `Rows`, `Iterate`这几个方法。在进行查询时可以使用多个方法来形成查询条件,条件函数如下:

* Id(interface{})
传入一个PK字段的值,作为查询条件,如果是复合主键,则
`Id(xorm.PK{1, 2})`
传入的两个参数按照struct中定义的顺序赋值
传入的两个参数按照struct中字段出现的顺序赋值

* Where(string, …interface{})
和Where语句中的条件基本相同,作为条件
Expand Down Expand Up @@ -501,6 +520,22 @@ user := new(User)
total, err := engine.Where("id >?", 1).Count(user)
```

<a name="67" id="67"></a>
### 5.7.Rows方法

Rows方法和Iterate方法类似,提供逐条执行查询到的记录的方法,不过Rows更加灵活好用。
```Go
user := new(User)
rows, err := engine.Where("id >?", 1).Rows(user)
if err != nil {
}
defer rows.Close()
for rows.Next() {
err = rows.Scan(user)
//...
}
```

<a name="70" id="70"></a>
## 6.更新数据

Expand Down Expand Up @@ -561,29 +596,33 @@ affected, err := engine.Id(id).Delete(user)
## 8.执行SQL查询

也可以直接执行一个SQL查询,即Select命令。在Postgres中支持原始SQL语句中使用 ` 和 ? 符号。

```Go
sql := "select * from userinfo"
results, err := engine.Query(sql)
```

当调用`Query`时,第一个返回值`results``[]map[string][]byte`的形式。

<a name="100" id="100"></a>
## 9.执行SQL命令

也可以直接执行一个SQL命令,即执行Insert, Update, Delete 等操作。同样在Postgres中支持原始SQL语句中使用 ` 和 ? 符号。
也可以直接执行一个SQL命令,即执行Insert, Update, Delete 等操作。此时不管数据库是何种类型,都可以使用 ` 和 ? 符号。

```Go
sql = "update userinfo set username=? where id=?"
sql = "update `userinfo` set username=? where id=?"
res, err := engine.Exec(sql, "xiaolun", 1)
```

<a name="110" id="110"></a>
## 10.事务处理
当使用事务处理时,需要创建Session对象。
当使用事务处理时,需要创建Session对象。在进行事物处理时,可以混用ORM方法和RAW方法,如下代码所示:

```Go
session := engine.NewSession()
defer session.Close()
// add Begin() before any action
err := session.Begin()
err := session.Begin()
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
_, err = session.Insert(&user1)
if err != nil {
Expand Down Expand Up @@ -638,16 +677,16 @@ engine.MapCacher(&user, nil)

不过需要特别注意不适用缓存或者需要手动编码的地方:

1. 在Get或者Find时使用了Cols方法,在开启缓存后此方法无效,系统仍旧会取出这个表中的所有字段。
1. 当使用了`Distinct`,`Having`,`GroupBy`方法将不会使用缓存

2. 在使用Exec方法执行了方法之后,可能会导致缓存与数据库不一致的地方。因此如果启用缓存,尽量避免使用Exec。如果必须使用,则需要在使用了Exec之后调用ClearCache手动做缓存清除的工作。比如:
2.`Get`或者`Find`时使用了`Cols`,`Omit`方法,则在开启缓存后此方法无效,系统仍旧会取出这个表中的所有字段。

3. 在使用Exec方法执行了方法之后,可能会导致缓存与数据库不一致的地方。因此如果启用缓存,尽量避免使用Exec。如果必须使用,则需要在使用了Exec之后调用ClearCache手动做缓存清除的工作。比如:
```Go
engine.Exec("update user set name = ? where id = ?", "xlw", 1)
engine.ClearCache(new(User))
```

ClearCacheBean

缓存的实现原理如下图所示:

![cache design](https://raw.github.com/lunny/xorm/master/docs/cache_design.png)
Expand Down

0 comments on commit 44a82b0

Please sign in to comment.