对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换  。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。

beego 中自带的 orm,

各主流的golang orm介绍

golang可以通过原始的 执行数据库的操作,也可以采用ORM执行。

当前较为主流/活跃的orm有gorm、xorm、gorose等

1、xorm

  • 文档

支持的数据库有:mysql、mymysql、postgres、tidb、sqlite、mssql、oracle;事务性支持

链式api

has, err := engine.Where("name = ?", name).Desc("id").Get(&user)
err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))).Find(&users)

支持原生sql操作;查询缓存;可根据数据库反转生成代码;级联加载;提供sql语句日志输出;支持批量查询处理

// 每次处理100条
// SELECT * FROM user Limit 0, 100
// SELECT * FROM user Limit 101, 100
err := engine.BufferSize(100).Iterate(&User{Name:name}, func(idx int, bean interface{}) error {
    user := bean.(*User)
    return nil
})

自动化的读写分离/主从式

dataSourceNameSlice := []string{masterDataSourceName, slave1DataSourceName, slave2DataSourceName}
engineGroup, err := xorm.NewEngineGroup(driverName, dataSourceNameSlice)
go get github.com/go-xorm/xorm

代码示例:

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/go-xorm/xorm"
	"github.com/micro/go-log"
)
//定义结构体(xorm支持双向映射)
type User struct {
	UserId    int64   `xorm:"pk autoincr"` //指定主键并自增
	Name       string  `xorm:"unique"`      //唯一的
	Age    float64
	Time       int64 `xorm:"updated"` //修改后自动更新时间
	CreateTime int64   `xorm:"created"` //创建时间
	//Version    int     `xorm:"version"` //乐观锁
}
//定义orm引擎
var x *xorm.Engine
func init() {
	var err error
	x, err = xorm.NewEngine("mysql", "root:[email protected](127.0.0.1:3306)/xorm?charset=utf8") //xorm代表数据库名称
	if err != nil {
		log.Fatal("数据库连接失败:", err)
	}
	//创建的表名称为User
	if err := x.Sync(new(User)); err != nil {
		log.Fatal("数据表同步失败:", err)
		//log.Fatal()
	}
}
func main()  {
	//执行对应的操作
}
//添加数据
func Insert(name string, age float64) (int64, bool) {
	user := new(User)
	user.Name = name
	user.Age = age
	affected, err := x.Insert(user) //affected:受影响的行
	if err != nil {
		return affected, false
	}
	return affected, true
}
//删除数据
func Del(id int64) {
	user := new(User)
	x.Id(id).Delete(user)
}

//修改数据
func update(id int64, user *User) bool {
	affected, err := x.Id(id).Update(user)
	if err != nil {
		log.Fatal("修改数据发生错误:", err)
	}
	if affected == 0 {
		return false // 未发生影响,即没有修改成功
	}
	return true
}
func ExecDb()  {
	sql:="delete from user where user_id=?"
	result, err := x.Exec(sql,"6") //原生sql操作 :可以用作 增 删 改(对数据有响应的操作)
	if err != nil {
		log.Fatal("执行数据库操作发生错误:", err)
	}
	fmt.Println(result.LastInsertId())
	affected, _ := result.RowsAffected()
	fmt.Println("受影响的行数是:",affected)
}
//查询方式1
func query01(id int64) *User {
	user := &User{UserId: id}
	is, err := x.Get(user)
	if err != nil {
		log.Fatal("查询数据发生错误:", err)
	}
	if !is {
		log.Fatal("查询的数据不存在")
	}
	return user
}
//查询方式02
func query02()  {
	sql:="select * from user where name=?"
	resultsSlice, err := x.Query(sql,"jz333")  //原生sql操作 :查询操作
	if err!=nil{
		log.Log("查询失败")
	}
	fmt.Println("开始查询。。。。")
	for _,value:=range resultsSlice{
		fmt.Println(string(value["user_id"]),string(value["name"]),string(value["age"]))
	}
}

2、gorm

hook机制(Before/After Create/Save/Update/Delete/Find);对象关系Has One, Has Many, Belongs To, Many To Many, Polymorphism;热加载;支持原生sql操作;事务性

链式api

tx := db.Where("name = ?", "jinzhu").Where("age = ?", 20).Find(&users)

支持的数据库有:mysql、postgre、sqlite、sqlserver

查询操作

// Get first record, order by primary key
db.First(&user)
//// SELECT * FROM users ORDER BY id LIMIT 1;
​
// plain sql
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// map
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;

代码示例:

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
	"github.com/micro/go-log"
	"time"
)
//gorm 用 tag 的方式来标识 mysql 里面的约束
type Like struct {
	ID        int    `gorm:"primary_key"`
	Ip        string `gorm:"type:varchar(20);not null;index:ip_idx"`
	Ua        string `gorm:"type:varchar(256);not null;"`
	Title     string `gorm:"type:varchar(128);not null;index:title_idx"`
	CreatedAt time.Time
}
var db *gorm.DB
func init() {
	var err error
	db, err = gorm.Open("mysql", "root:[email protected](127.0.0.1:3306)/testdb?charset=utf8")
	if err != nil {
		log.Fatal("数据库连接出现了问题:", err)
		return
	}
}
//特别注意:结构体名称为:Like,创建的表的名称为:likes
func createTable() {
	if !db.HasTable(&Like{}) {
		err := db.CreateTable(&Like{}).Error
		if err != nil {
			fmt.Print("创建表失败", err)
			return
		}
		fmt.Println("添加表成功")
		return
	}
	fmt.Println("数据表已经存在")
}
func insert() {
	like := &Like{
		Ip:        "ip",
		Ua:        "ua",
		Title:     "title",
		CreatedAt: time.Now(),
	}
	err := db.Create(like).Error
	if err != nil {
		fmt.Println("添加数据失败:", err)
		return
	}
	fmt.Println("添加数据成功")
}
func del()  {
	result := db.Where(&Like{ID: 2}).Delete(Like{})
	fmt.Println("受影响的行:",result.RowsAffected)
}
func update()  {
	db.Model(&Like{}).Update("Ip","127.0.0.1") //修改方式1
	result := db.Model(&Like{ID:2}).Update(Like{Ua: "admin2", Title: "gorm2 application"})//条件更新 Like{ID:3}
	fmt.Println("受影响的行:",result.RowsAffected)

}
func query() {
	likes:=make([]Like,0) //会自动扩容
	db.Where("ip=?","ip").Find(&likes) //查询到的有可能为多行,所以采用结构体切片
	for _,like:=range likes{
		fmt.Println("查询到的数据是:",like.ID,like.Title)
	}
}
func DbTransaction() error {
	tx:=db.Begin()//开启事务
	tempDb:=tx.Create(&Like{Title:"gorm的事务:"})
	if err:=tempDb.Error;err!=nil{
		tx.Rollback()//出现错误,回滚
		return err
	}
	tx.Commit()//提交
	return nil
}
//支持原生的sql:增、删、改
func ExecSql(id int)  {
	sql:="delete from likes where id=?"
	tempDb:=db.Exec(sql,id)
	fmt.Println(tempDb.RowsAffected)
}
//支持原生的sql:查询
//支持原生的sql:查询
func ExecQuery(id int)  {
	sql:="select * from likes where id=?"
	like:=&Like{}
	db.Raw(sql,id).Find(like)
	fmt.Println(like.Title,like.Ua)
}
func main() {
  //createTable()
  insert()
 // update()
  query()
  //del()
}

3、gorose

gorose相关内容再次就不用示例演示了。具体内容可以参考一下资料。