ORM 组件

ORM 组件我们依赖的开源包是 github.com/go-xorm/xorm

按照组件的设计,我们定义了自己的 ORM 结构对其进行了组合,在保留其原生的功能之外,以便扩展。

// yago/coms/orm/orm.go
type Orm struct {
    *xorm.Engine
}

所以你可以查看 xorm 官方文档 来获取所有支持的 api。

本文中仅介绍部分常用的 api 以及扩展的 api。

1. 配置 ORM 组件

[db]
host = "127.0.0.1"
user = "user"
password = "password"
port = "3306"
database = "db"
prefix =""
timezone = "Asia/Shanghai"
charset = "utf8"
max_life_time = 8 # 连接最大生命周期 8s
max_idle_conn = 20 # 最多空闲连接数 20
max_open_conn = 500 # 最大打开连接数
show_log = true # 是否开启日志

我们在模版 app.toml 中默认配置开启了 ORM 组件,可根据实际情况进行调整。

2. 使用 ORM 组件

2.1. 定义表结构

// 下文以 user 表为例
type UserDao struct {
    Id    int64  `json:"id" xorm:"autoincr"`
    Name  string `json:"name"`
    Ctime string `json:"ctime" xorm:"created"`
    Utime string `json:"utime" xorm:"updated"`
}

func (d *UserDao) TableName() string {
    return "user"
}

2.2. 新增记录

  • 新增一行
user := &homedao.UserDao{
    Name:  "zhangsan",
}

_, err := orm.Ins().Insert(user)

调用 orm.Ins() 会返回 orm.Orm 实例,因其对 xorm.Engine 进行了扩展,我们可以使用 xorm.Engine 的所有 api。

  • 新增多行
users := []*homedao.UserDao{
    {Name:"lisi"},
    {Name:"wangwu"},
}
_, err := orm.Ins().Insert(users)

2.3. 查询单行记录

user := &homedao.UserDao{Id: id}
exists, err := orm.Ins().Get(user)

2.4. 删除

  • 删除一行
user := &homedao.UserDao{Id: id}
n, err := orm.Ins().Delete(user)
  • 删除多行
n,err := orm.Ins().Where("id > ?", 100).Delete(new(homedao.UserDao))

2.5. 修改

  • 推荐用法
// 推荐用法
attrs := g.Hash{}
attrs["name"] = "hello"

tableName := new(homedao.UserDao).TableName()

_, err := orm.Ins().Table(tableName).Where("id=?",id).Update(attrs)
  • 简单用法
user := &homedao.UserDao{Id: id}
user.Name = "kowloon"
n, err := orm.Ins().Update(user)

注意:简单用法里面,如果赋值为字段的零值时(整数的 0, 字符串的 空串), orm 会忽略掉不更新

2.6. 查询

  • 查询多行多列
users := make([]*homedao.UserDao, 0)
err := orm.Ins().Table(new(homedao.UserDao).TableName()).
        Select("*").
        Where("id > ?", 10).
        Find(&users)
  • 查询多行单列
userIds := make([]int64, 0)
err := orm.Ins().Table(new(homedao.UserDao).TableName()).
        Cols("id").
        Find(&userIds)
  • 查询总数
total, err := orm.Ins().Table(new(homedao.UserDao)).
            Where("id  > ?", 10).
            Count()
  • 使用原生 sql
sql := "select * from user"
results, err := orm.Ins().Query(sql)

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

2.7. 分页 + Join + 排序查询

  • 新增表结构
// 此处新增一个表结构 user_detail, user_id 与 user 表关联
type DetailDao struct {
    Id    int64  `json:"id" xorm:"autoincr"`
    UserId  int64 `json:"user_id"`
    Phone string `json:"phone"`
}

func (d *DetailDao) TableName() string {
    return "user_detail"
}

// 再扩展一个新的结构体,来用存放连表查询的结构
type UserDetail struct {
    UserDao `xorm:"extends"`
    Phone string `json:"phone"`
}
  • 查询
userDetails := make([]*homedao.UserDetail, 0)

query := orm.Ins().Table(new(homedao.UserDao)).Alias("t").
        Select("t.*,d.phone").
        Join("INNER", []string{new(homedao.DetailDao).TableName(), "d"}, "d.user_id=t.id").
        Where("t.id > 10", 0)

query.Limit(pagesize,(page-1)*pagesize)
query.OrderBy("t.id desc")

// total 为总页数,userDetails 为结果集列表
total, err := query.FindAndCount(&userDetails)

2.8. 事务

yago 扩展了 xorm 的事务功能,增加了一个 Transactional 方法

err := orm.Ins().Transactional(func(session *xorm.Session) error {
    user := &homedao.UserDao{
        Name: "law",
    }
    if _, err := session.Insert(user);err != nil{
        // log
        return err
    }
    userDetail := &homedao.DetailDao{
        UserId: user.Id,
        Phone: "13800000000",
    }

    if _, err := session.Insert(userDetail);err != nil{
        // log
        return err
    }
    return nil
})

2.9. Upsert

yago 扩展了一个 Upsert 的功能,用来处理添加或者修改数据库时需要保障原子性的业务场景

// 非事务下使用
res, err := orm.Ins().Upsert(new(homedao.HomeDao), g.Hash{
   "name":     "KowloonZh4",
   "uuid": "P4HgNK5n2ATfMX6w",
  })


// 事务下使用
res, err := orm.Ins().Upsert("user", g.Hash{
   "name":     "KowloonZh",
   "uuid": "P4HgNK5n2ATfMX6w",
  },orm.WithSession(session))

注:表名参数可以是一个字串,也可以是一个 xorm 的 ORM 结构体实例

results matching ""

    No results matching ""