xorm

关于XORM中Mapper的使用

XORM中的Mapper是一个接口机制,专门用来在程序名称和数据库名称之间进行转换。XORM库中带有三种Mapper的实现,SnakeMapper, SameMapper 以及 GonicMapper。同时为了方便还提供了CacheMapper, PrefixMapper 以及 SuffixMapper,这几种Mapper可以和前面的组合使用。

SnakeMapper

SnakeMapper是默认的映射机制,他支持数据库表采用匈牙利命名法,而程序中采用驼峰式命名法。下面是一些常见的映射:

表中名称 程序名称
user_info UserInfo
id Id

SameMapper

SameMapper就是数据库中的命名法和程序中是相同的。那么鉴于在Go中,基本上要求首字母必须大写。所以一般都是表中和程序中均采用驼峰式命名。下面是一些常见的映射:

表中名称 程序名称
UserInfo UserInfo
Id Id

GonicMapper

GonicMapper是在SnakeMapper的基础上增加了特例,对于常见的缩写不新增下划线处理。这个同时也符合golint的规则。下面是一些常见的映射:

表中名称 程序名称
user_info UserInfo
id ID
url URL

CacheMapper

CacheMapper 通过使用一个map来将已经映射过的内容保存起来,下次直接查找即可获得。

PrefixMapper

PrefixMapper 前缀映射可以组合SnakeMapper, SameMapper或者GonicMapper来在表名或者字段名的映射完成后,再新增一个固定的前缀。比如和SnakeMapper组合:

engine.SetTableMapper(core.NewPrefixMapper(core.SnakeMapper{}, "tb_"))
engine.SetColumnMapper(core.SnakeMapper{})

那么对于结构体User,数据库中对应的表名即为tb_user,而表中字段名比如id对应的程序中结构体字段名仍为Id

SuffixMapper

SuffixMapper 后缀映射类似与前缀映射,也可以组合SnakeMapper, SameMapper或者GonicMapper来在表名或者字段名的映射完成后,再新增一个固定的前缀。比如和SnakeMapper组合:

engine.SetTableMapper(core.NewSuffixMapper(core.SnakeMapper{}, "_table"))
engine.SetColumnMapper(core.SnakeMapper{})

那么对于结构体User,数据库中对应的表名即为user_table,而表中字段名比如id对应的程序中结构体字段名仍为Id

表名和字段名分别映射

在前面的例子中也看到了,这种映射可以对表名和字段名采用相同的映射,也可以表名和字段名采用不同的映射方案。

  • 表名和字段名使用相同映射方案

    engine.SetMapper(mapper)
    
  • 表名和字段名使用不同的映射方案

    engine.SetTableMapper(mapper1)
    engine.SetColumnMapper(mapper2)
    

最后,关于名称映射更多的方法可以参考XORM文档 使用Table和Tag改变名称映射

在Xorm中使用Join和Extends标记

本文主要针对对Xorm已经有了一定了解的读者,如果您是第一次了解Xorm,请先阅读xorm操作手册

Xorm的基本操作都是比较简单的,可能大家也都比较熟悉了。今天主要讲解extends标记和join的使用。通过使用join和extends,可以解决许多需要级联进行的操作。

一般我们会针对数据库中的每一个表,建立一个对应的结构体。比如:

type User struct {
    Id int64
    Name string
}

type Account struct {
    Id int64
    UserId int64 `xorm:"index"`
    Amount int64
}

type Car struct {
    Id int64
    UserId int64 `xorm:"index"`
    Type int
}

我们定义了三个结构体,对应数据库的三个表,我们在启动时通过:

engine.Sync2(new(User), new(Account), new(Car))

来进行数据库结构的同步。在这个数据库结构中,我们假设一个用户拥有一个Account,一个用户拥有多个Car。

OK。复杂需求来了。

1)我们需要获得所有的用户的姓名和对应的账户的余额:

type AccountUser struct {
    Account `xorm:"extends"`
    User `xorm:"extends"`
}

var accounts = make([]*AccountUser, 0)
engine.Table("account").Join("INNER", "user", "account.user_id = user.id").Find(&accounts)

OK。这样,我们就取出了user和对应的account,我们通过account.Account可以获取到Account的信息,通过account.User可以获取到User的信息。

这个是两个表Join,那么如果是三个表也是类似的做法。

2)我只需要用户名,不需要其它的内容:

type AccountUser struct {
    Account `xorm:"extends"`
    Name string
}
var accounts = make([]*AccountUser, 0)
engine.Table("account").Join("INNER", "user", "account.user_id = user.id").Find(&accounts)

其实我们代码也是差不多的,但是这里我们实际上在查询数据库的时候是查询了user表的所有内容的。只是在最后赋值到结构体时,按需赋值。

3)更复杂的,我们还想知道每人有几辆车。

type AccountUser struct {
    Account `xorm:"extends"`
    Name string
    NumCars int
}
var accounts = make([]*AccountUser, 0)
engine.Sql("select account.*, user.name, (select count(id) from car where car.user_id = user.id) as num_cars from account, user where account.user_id = user.id").Find(&accounts)

在这样的复杂需求下,我们使用了Sql函数和extends标记结合来完成这个操作。

XORM的七种武器

xorm 是一个简单而强大的 Go 语言开源 ORM 库. 通过它可以使数据库操作非常简便。

xorm 的七种武器

xorm 是一个简单而强大的 Go 语言开源 ORM 库. 通过它可以使数据库操作非常简便。

了解过 Go 的人可能会有疑问,Go 已经提供了 database/sql 接口,操作各种数据库接口都一致了,还有必要再使用 ORM 吗?也有人觉得对于复杂 SQL 语句,ORM 是无法应付的。

是的,xorm 不是为了取代 SQL,它甚至可以和 SQL 混用,它是在 databse/sql 接口的基础之上提供了更多的特性。我们将这些功能和特性比喻成七种武器,来帮助开发者快速的完成数据库的操作。