xorm/README_CN.md

380 lines
10 KiB
Markdown
Raw Normal View History

2013-05-16 06:12:27 +00:00
# xorm
2013-05-12 05:43:09 +00:00
[English](https://github.com/lunny/xorm/blob/master/README.md)
2013-05-03 07:32:52 +00:00
xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。
2013-05-08 13:42:22 +00:00
2013-06-08 04:47:28 +00:00
[![Build Status](https://drone.io/github.com/lunny/xorm/status.png)](https://drone.io/github.com/lunny/xorm/latest)
2013-05-16 06:12:27 +00:00
## 驱动支持
2013-05-08 13:42:22 +00:00
目前支持的Go数据库驱动如下
2013-05-03 07:32:52 +00:00
2013-05-11 10:38:43 +00:00
* Mysql: [github.com/Go-SQL-Driver/MySQL](https://github.com/Go-SQL-Driver/MySQL)
2013-05-03 07:32:52 +00:00
2013-05-11 10:38:43 +00:00
* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
## 更新日志
* **v0.1.7** : 新增IConnectPool接口以及NoneConnectPool, SysConnectPool, SimpleConnectPool三种实现可以选择不使用连接池使用系统连接池和使用自带连接池三种实现默认为SysConnectPool即系统自带的连接池。同时支持自定义连接池。Engine新增Close方法在系统退出时应调用此方法。
* **v0.1.6** : 新增Conversion支持自定义类型到数据库类型的转换新增查询结构体自动检测匿名成员支持新增单向映射支持
2013-06-22 01:05:19 +00:00
* **v0.1.5** : 新增对多线程的支持新增Sql()函数支持任意sql语句的struct查询Get函数返回值变动MakeSession和Create函数被NewSession和NewEngine函数替代
* **v0.1.4** : Get函数和Find函数新增简单的级联载入功能对更多的数据库类型支持。
* **v0.1.3** : Find函数现在支持传入Slice或者Map当传入Map时key为id新增Table函数以为多表和临时表进行支持。
* **v0.1.2** : Insert函数支持混合struct和slice指针传入并根据数据库类型自动批量插入同时自动添加事务
2013-05-11 10:38:43 +00:00
* **v0.1.1** : 添加 Id, In 函数,改善 README 文档
* **v0.1.0** : 初始化工程
2013-05-09 02:48:30 +00:00
## 特性
2013-05-16 06:12:27 +00:00
* 支持Struct和数据库表之间的映射映射方式支持命名约定和Tag两种方式映射支持继承
2013-05-09 02:48:30 +00:00
2013-05-11 10:38:43 +00:00
* 事务支持
2013-05-09 02:48:30 +00:00
2013-05-11 10:38:43 +00:00
* 同时支持原始SQL语句和ORM操作的混合执行
2013-05-09 02:48:30 +00:00
2013-05-11 10:38:43 +00:00
* 使用连写来简化调用
2013-05-09 02:48:30 +00:00
* 支持使用Id, In, Where, Limit, Join, Having, Table, Sql等函数和结构体等方式作为条件
* 支持数据库连接池
* 支持级联加载struct
2013-05-03 07:32:52 +00:00
2013-05-08 13:42:22 +00:00
## 安装
go get github.com/lunny/xorm
2013-05-03 07:32:52 +00:00
2013-05-08 13:42:22 +00:00
## 快速开始
2013-05-03 07:32:52 +00:00
2013-06-22 01:02:01 +00:00
1.创建数据库引擎这个函数的参数和sql.Open相同但不会立即创建连接 (例如: mysql),注意Create方法将在后续版本中被弃用请使用NewEngine方法。
2013-05-11 07:45:24 +00:00
```Go
2013-05-11 13:27:36 +00:00
import (
_ "github.com/Go-SQL-Driver/MySQL"
"github.com/lunny/xorm"
2013-05-12 06:04:14 +00:00
)
2013-06-22 01:02:01 +00:00
engine, err := xorm.NewEngine("mysql", "root:123@/test?charset=utf8")
defer engine.Close()
2013-05-11 13:27:36 +00:00
```
2013-05-09 01:56:58 +00:00
or
```Go
2013-05-11 13:27:36 +00:00
import (
_ "github.com/mattn/go-sqlite3"
"github.com/lunny/xorm"
)
engine, err = xorm.NewEngine("sqlite3", "./test.db")
defer engine.Close()
2013-05-11 13:27:36 +00:00
```
2013-05-12 05:43:09 +00:00
1.1.默认将不会显示自动生成的SQL语句如果要显示则需要设置
```Go
2013-05-12 05:43:09 +00:00
engine.ShowSQL = true
```
1.2.如果要更换连接池实现可使用SetPool方法
```Go
err = engine.SetPool(NewSimpleConnectPool())
```
2013-05-03 07:32:52 +00:00
2013-05-12 05:43:09 +00:00
2.所有的ORM操作都针对一个或多个结构体一个结构体对应一张表定义一个结构体如下
2013-05-03 07:32:52 +00:00
```Go
2013-05-11 13:27:36 +00:00
type User struct {
Id int
Name string
Age int `xorm:"-"`
}
```
2013-05-12 05:43:09 +00:00
2013-05-12 06:25:36 +00:00
2.1 详细映射规则,请查看[映射规则](#mapping)
2013-05-03 07:32:52 +00:00
2013-05-11 10:38:43 +00:00
3.在程序初始化时,可能会需要创建表
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
err := engine.CreateTables(&User{})
```
2013-05-03 07:32:52 +00:00
2013-06-22 01:02:01 +00:00
4.然后,可以将一个结构体作为一条记录插入到表中, 如果插入成功将会返回id同时User对象的Id也会被自动赋值。
2013-05-11 13:27:36 +00:00
```Go
2013-06-22 01:02:01 +00:00
user := &User{Name:"lunny"}
id, err := engine.Insert(user)
fmt.Println(user.Id)
2013-05-11 13:27:36 +00:00
```
2013-05-08 13:42:22 +00:00
或者执行更新操作:
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
user := User{Name:"xlw"}
rows, err := engine.Update(&user, &User{Id:1})
// rows, err := engine.Where("id = ?", 1).Update(&user)
// or rows, err := engine.Id(1).Update(&user)
```
2013-05-08 13:42:22 +00:00
2013-05-11 10:38:43 +00:00
5.获取单个对象可以用Get方法
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
var user = User{Id:27}
2013-06-22 01:02:01 +00:00
has, err := engine.Get(&user)
// or has, err := engine.Id(27).Get(&user)
2013-05-11 13:27:36 +00:00
var user = User{Name:"xlw"}
2013-06-22 01:02:01 +00:00
has, err := engine.Get(&user)
2013-05-11 13:27:36 +00:00
```
2013-05-08 13:42:22 +00:00
2013-06-22 01:02:01 +00:00
6.获取多个对象到一个Slice或一个Map对象中可以用Find方法如果传入的是map则key中存放的是id
2013-05-11 10:38:43 +00:00
```Go
2013-05-11 13:27:36 +00:00
var everyone []Userinfo
err := engine.Find(&everyone)
users := make(map[int64]Userinfo)
err := engine.Find(&users)
2013-05-11 13:27:36 +00:00
```
2013-05-11 10:38:43 +00:00
6.1 你也可以使用Where和Limit方法设定条件和查询数量
2013-05-08 13:42:22 +00:00
```Go
2013-05-11 13:27:36 +00:00
var allusers []Userinfo
err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
```
2013-05-11 10:38:43 +00:00
6.2 用一个结构体作为查询条件也是允许的
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
var tenusers []Userinfo
err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 offset 0
```
2013-05-08 13:42:22 +00:00
2013-05-11 10:38:43 +00:00
6.3 也可以调用In函数
```Go
2013-05-11 13:27:36 +00:00
var tenusers []Userinfo
err := engine.In("id", 1, 3, 5).Find(&tenusers) //Get All id in (1, 3, 5)
```
2013-05-08 13:42:22 +00:00
2013-05-11 10:38:43 +00:00
7.Delete方法
2013-05-08 13:42:22 +00:00
```Go
2013-06-22 01:02:01 +00:00
num, err := engine.Delete(&User{Id:1})
// or num, err := engine.Id(1).Delete(&User{})
2013-05-11 13:27:36 +00:00
```
2013-05-11 10:38:43 +00:00
8.Count方法
```Go
2013-05-11 13:27:36 +00:00
total, err := engine.Count(&User{Name:"xlw"})
```
2013-05-08 13:42:22 +00:00
2013-05-16 07:03:08 +00:00
## 直接执行SQL语句
2013-05-16 06:12:27 +00:00
2013-05-08 13:42:22 +00:00
当然如果你想直接使用SQL语句进行操作也是允许的。
2013-05-11 10:38:43 +00:00
如果执行Select请用Query()
```Go
2013-05-11 13:27:36 +00:00
sql := "select * from userinfo"
results, err := engine.Query(sql)
```
2013-05-11 10:38:43 +00:00
如果执行Insert Update Delete 等操作请用Exec()
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
sql = "update userinfo set username=? where id=?"
res, err := engine.Exec(sql, "xiaolun", 1)
```
2013-05-08 13:42:22 +00:00
2013-05-16 07:03:08 +00:00
## 高级用法
2013-05-16 06:12:27 +00:00
2013-05-12 06:25:36 +00:00
<a name="mapping" id="mapping"></a>
2013-06-22 01:02:01 +00:00
更高级的用法我们必须要使用session对象session对象在创建时会立刻创建一个数据库连接。注意MakeSession方法将会在后续版本中移除请使用NewSession方法替代。
2013-05-11 13:27:36 +00:00
```Go
2013-06-22 01:02:01 +00:00
session := engine.NewSession()
2013-05-11 13:27:36 +00:00
defer session.Close()
```
2013-05-08 13:42:22 +00:00
1.session对象同样也可以查询
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
var user Userinfo
session.Where("id=?", 27).Get(&user)
2013-05-08 13:42:22 +00:00
2013-05-11 13:27:36 +00:00
var user2 Userinfo
session.Where("name = ?", "john").Get(&user3) // more complex query
2013-05-08 13:42:22 +00:00
2013-05-11 13:27:36 +00:00
var user3 Userinfo
session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more complex
```
2013-05-08 13:42:22 +00:00
2.获取多个对象
2013-05-11 13:27:36 +00:00
```Go
2013-05-11 13:27:36 +00:00
var allusers []Userinfo
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
2013-05-08 13:42:22 +00:00
2013-05-11 13:27:36 +00:00
var tenusers []Userinfo
err := session.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 if omit offset the default is 0
2013-05-08 13:42:22 +00:00
2013-05-11 13:27:36 +00:00
var everyone []Userinfo
err := session.Find(&everyone)
```
2013-05-08 13:42:22 +00:00
3.事务处理
```Go
2013-05-11 13:27:36 +00:00
// add Begin() before any action
2013-06-22 01:02:01 +00:00
err := session.Begin()
2013-05-11 13:27:36 +00:00
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
_, err = session.Insert(&user1)
if err != nil {
session.Rollback()
return
}
user2 := Userinfo{Username: "yyy"}
_, err = session.Where("id = ?", 2).Update(&user2)
if err != nil {
session.Rollback()
return
}
_, err = session.Delete(&user2)
if err != nil {
session.Rollback()
return
}
// add Commit() after all actions
err = session.Commit()
if err != nil {
return
}
```
4.混合型事务这个事务中既有直接的SQL语句又有ORM方法
```Go
2013-05-11 13:27:36 +00:00
// add Begin() before any action
2013-06-22 01:02:01 +00:00
err := session.Begin()
2013-05-11 13:27:36 +00:00
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
_, err = session.Insert(&user1)
if err != nil {
session.Rollback()
return
}
user2 := Userinfo{Username: "yyy"}
_, err = session.Where("id = ?", 2).Update(&user2)
if err != nil {
session.Rollback()
return
}
_, err = session.Exec("delete from userinfo where username = ?", user2.Username)
if err != nil {
session.Rollback()
return
}
// add Commit() after all actions
err = session.Commit()
if err != nil {
return
}
```
5.匿名结构体继承:
请查看Examples中的derive.go文件。
2013-05-08 13:42:22 +00:00
2013-05-16 06:12:27 +00:00
## 映射规则
2013-05-08 14:50:19 +00:00
1.Struct 和 Struct 的field名字应该为Pascal式命名默认的映射规则将转换成用下划线连接的命名规则这个映射是自动进行的当然你可以通过修改Engine的成员Mapper来改变它。
2013-05-08 13:42:22 +00:00
例如:
结构体的名字UserInfo将会自动对应数据库中的名为user_info的表。
UserInfo中的成员UserName将会自动对应名为user_name的字段。
2013-05-08 14:50:19 +00:00
2.当然你也可以改变这个规则这有两种方法。一是实现你自己的IMapper你可以在mapper.go中查看到这个接口。然后设置到 engine.Mapper。
2013-05-08 13:42:22 +00:00
另外一种方法就通过Field Tag来进行改变关于Field Tag请参考Go的语言文档如下列出了Tag中可用的关键字及其对应的意义
<table>
<tr>
<td>name</td><td>当前field对应的字段的名称可选</td>
</tr>
<tr>
<td>pk</td><td>是否是Primary Key</td>
</tr>
<tr>
<td>int(11)/varchar(50)/text/date/datetime/blob/decimal(26,2)</td><td>字段类型</td>
2013-05-08 13:42:22 +00:00
</tr>
<tr>
<td>autoincr</td><td>是否是自增</td>
</tr>
<tr>
<td>[not ]null</td><td>是否可以为空</td>
</tr>
<tr>
<td>unique</td><td>是否是唯一</td>
</tr>
<tr>
<td>extends</td><td>应用于一个匿名结构体之上,表示此匿名结构体的成员也映射到数据库中</td>
</tr>
2013-05-08 13:42:22 +00:00
<tr>
<td>-</td><td>这个Field将不进行字段映射</td>
</tr>
</table>
2013-05-11 10:38:43 +00:00
例如:
```Go
2013-05-11 13:27:36 +00:00
type Userinfo struct {
Uid int `xorm:"id pk not null autoincr"`
Username string
Departname string
Alias string `xorm:"-"`
Created time.Time
}
```
3.对于自定义的表名可以用Table函数进行操作比如
```Go
// batch create tables
for i := 0; i < 10; i++ {
engine.Table(fmt.Sprintf("user_%v", i)).CreateTable(&Userinfo{})
}
// insert into table according id
user := Userinfo{Uid: 25, Username:"sslfs"}
engine.Table(fmt.Sprintf("user_%v", user.Uid % 10)).Insert(&user)
```
2013-05-11 10:38:43 +00:00
2013-05-16 07:03:08 +00:00
## 文档
2013-05-16 06:12:27 +00:00
2013-05-11 07:45:24 +00:00
请访问 [GoWalker](http://gowalker.org/github.com/lunny/xorm) 查看详细文档
2013-05-08 13:42:22 +00:00
2013-05-16 07:03:08 +00:00
## FAQ
2013-05-16 06:12:27 +00:00
2013-05-11 10:38:43 +00:00
1.问xorm的tag和json的tag如何同时起作用
2013-05-08 13:42:22 +00:00
2013-05-11 10:38:43 +00:00
答案:使用空格分开
2013-05-08 13:42:22 +00:00
```Go
2013-05-11 13:27:36 +00:00
type User struct {
Name string `json:"name" xorm:"name"`
}
```
2013-05-11 10:38:43 +00:00
2.问xorm是否带有连接池
答案database/sql默认就有连接池因此xorm本身没有内建连接池在使用过程中会自动调用database/sql的实现。
2013-05-03 07:32:52 +00:00
## LICENSE
2013-05-11 13:27:36 +00:00
BSD License
[http://creativecommons.org/licenses/BSD/](http://creativecommons.org/licenses/BSD/)