Orm 增删改查

如下就可以创建一个简单的Orm实例:

  1. var o orm.Ormer
  2. o = orm.NewOrm() // 创建一个 Ormer
  3. // NewOrm 的同时会执行 orm.BootStrap (整个 app 只执行一次),用以验证模型之间的定义并缓存。

大多数情况下,你应该尽量复用Orm 实例,因为本身Orm实例被设计为无状态的,一个数据库对应一个Orm实例。

但是在使用事务的时候,我们会返回TxOrm的实例,它本身是有状态的,一个事务对应一个TxOrm实例。在使用TxOrm时候,任何衍生查询都是在该事务内。

Insert 和 InsertWithCtx

定义:

  1. Insert(md interface{}) (int64, error)
  2. InsertWithCtx(ctx context.Context, md interface{}) (int64, error)

例如:

  1. user := new(User)
  2. id, err = Ormer.Insert(user)

这两个方法都只接收指针做为参数。

InsertOrUpdate 和 InsertOrUpdateWithCtx

定义:

  1. InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
  2. InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error)

这两个方法在不同的方言之下有不同的效果:

  • 对于 MySQL 来说,是执行 ON DUPLICATE KEY。因此最后一个参数colConflictAndArgs 不需要传;
  • 对于 PostgreSQL 来说,是执行 ON CONFLICT cols DO UPDATE SET,因此最后一个参数colConflictAndArgs可以传入具体的列名;
  • 对于别的方言来说,你需要确认它们支持类似的语法;

InsertMulti 和 InsertMultiWithCtx

用于执行批量插入:

  1. InsertMulti(bulk int, mds interface{}) (int64, error)
  2. InsertMultiWithCtx(ctx context.Context, bulk int, mds interface{}) (int64, error)

参数bulk是每一次批量插入的时候插入的数量。例如bulk<=1代表每一批插入一条数据,而如果bulk=3代表每次插入三条数据。你需要仔细选择批次大小,它对插入性能有很大影响。大多数情况下,你可以把bulk设置成数据量大小。

mds必须是一个数组,或者是一个切片。

第一个返回值表示最终插入了多少数据。

Update 和 UpdateWithCtx

使用主键来更新数据。也就是如果你使用这个方法,Beego 会尝试读取里面的主键值,而后将主键作为更新的条件。

定义是:

  1. Update(md interface{}, cols ...string) (int64, error)
  2. UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)

如果你没有指定 cols 参数,那么所有的列都会被更新。

第一个返回值是受影响的行数。

Delete 和 DeleteWithCtx

使用主键来删除数据,定义:

  1. Delete(md interface{}, cols ...string) (int64, error)
  2. DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error)

第一个返回值是受影响的行数。

Read 和 ReadWithCtx

方法定义为:

  1. Read(md interface{}, cols ...string) error
  2. ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error

该方法的特点是:

  • 读取到的数据会被放到 md
  • 如果传入了 cols 参数,那么只会选取特定的列;

例如:

  1. // 读取全部列
  2. u = &User{Id: user.Id}
  3. err = Ormer.Read(u)
  4. // 只读取用户名这一个列
  5. u = &User{}
  6. err = Ormer.Read(u, "UserName")

ReadForUpdate 和 ReadForUpdateWithCtx

这两个方法的定义是:

  1. ReadForUpdate(md interface{}, cols ...string) error
  2. ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error

这两个方法类似于ReadReadWithCtx,所不同的是,这两个方法在查询的时候加上 FOR UPDATE,因此常用于事务内部。

但是并不是所有的数据库都支持 FOR UPDATE 语句,所以你在使用的时候要首先确认自己的数据库支持 FOR UPDATE 的用法。

ReadOrCreate 和 ReadOrCreateWithCtx

它们的定义是:

  1. ReadOrCreate(md interface{}, col1 string, cols ...string) (bool, int64, error)
  2. ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error)

从数据库中查找数据,如果数据不存在,那么就插入。

需要注意的是,“查找-判断-插入”这三个动作并不是原子的,也不是线程安全的。因此在并发环境下,它的行为可能会超出你的预期,比如说有两个 goroutine 同时判断到数据不存在,那么它们都会尝试插入。

Raw 和 RawWithContext

  1. Raw(query string, args ...interface{}) RawSeter
  2. RawWithCtx(ctx context.Context, query string, args ...interface{}) RawSeter

执行原生查询。Beego 并不可能支持所有的 SQL 语法特性,因此在某些特殊情况下,你需要使用原生查询。

它会返回一个RawSeter,你可以参阅RawSeter来确认该如何处理查询返回的结果集。

LoadRelated 和 LoadRelatedWithCtx

它们的定义是:

  1. LoadRelated(md interface{}, name string, args ...utils.KV) (int64, error)
  2. LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...utils.KV) (int64, error)

LoadRelatedWithCtx 已经被弃用。

这两个方法用于加载关联表的数据,例如:

  1. o.LoadRelated(post,"Tags")
  2. for _,tag := range post.Tags{
  3. // 业务代码
  4. }

该方法对

注意到,这两个方法最后一个参数都是传入 KV 值,目前这些 KV 值被定义在 hints 包里面,有:

  • hints.DefaultRelDepth:设置关联表的解析深度为默认值 2;
  • hints.RelDepth:设置自定义的关联表深度;
  • hints.Limit:设置查询返回的行数;
  • hints.Offset:设置查询结果的偏移量;
  • hints.OrderBy:设置查询的排序;

这个方法要谨慎使用,尤其是在偏移量或者深度设置的值比较大的情况下,响应时间会比较长。

QueryM2M 和 QueryM2MWithCtx

定义是:

  1. QueryM2M(md interface{}, name string) QueryM2Mer
  2. QueryM2MWithCtx(ctx context.Context, md interface{}, name string) QueryM2Mer

QueryM2MWithCtx已经不建议使用了,因为ctx参数毫无效果。

这两个方法都是返回一个QueryM2Mer,用于查询多对多关联关系的数据。可以参考[./query.md#QueryM2Mer]