ORM定义:

ORM(对象关系映射).它的作用是在关系型数据库和对象之间作一个映射.在操作数据库的时候.就不需要在和复杂的SQL语句打交道了.像平常操作对象一样.ORM组成含义如下.
O(Object.对象模型):实体对象.即在程序中根据数据库表结构建立的一个个实体.(Entity)
R(Relation.关系型数据库的数据结构):建立的数据库表.
M(Mapping.映射):从R(数据库表)到O(对象模型)的映射.可通过XML文件映射.
如图所示.

为什么使用ORM:
程序的开发中.数据库保存的表 字段与程序中的实体是没有关联的.实现持久化不方便.如何实现持久化.一种简单的方式是硬编码.为每一种可能的数据库访问操作提供单独的方法.这种方案存在以下不足.
1).持久化层缺乏弹性.一旦出现业务需求的变更.就必须修改持久化层的接口.
2).持久化层同时与域模型及关系型数据库模型绑定.不管模型还是关系数据库模型发生变化.都要修改持久化层代码.增加了维护难度.
ORM提供了实现了持久层的另一种模式.它采用映射数据来描述对象关系的映射.使得ORM中间件能在任何一个应用的业务逻辑层和数据层之间充当桥梁.ORM的方法论基于以下三个核心原则.
1).简单:以最基本的形式进行数据建模.
2).传达性:数据库结构被任何人都能理解的语言文档化.
3).精确性:基于数据模型创建正确标准化的结构.

在目前的企业应用系统设计中.MVC为主要的系统架构模式.MVC中的Model包含了复杂的业务逻辑和数据逻辑.以及数据存取机制(如数据库的连接 SQL生成和Statement创建.还有ResultSet结果集的读取等).将这些复杂的业务逻辑和数据逻辑分离.以将这些系统的紧耦合关系转化为松耦合关系.是降低系统耦合度迫切要做的.也是持久化要做的工作.MVV模式实现了架构上将表现层(即View)和数据处理层(即Model)分离的解耦合.而持久化的设计原则实现了数据处理内部的业务逻辑和数据逻辑分离的解耦合.
Gorm的使用:

1).数据库连接.
Gorm数据库连接和database/sql包的连接方式一样.直接用gorm.Open()方法传入数据库地址即可.还可以使用db.DB()对象的SetMaxIdleConns()和SetMaxOpenConns方法设置连接信息.SetMaxIdleConns()方法用于设置空闲连接池中的最大连接数.SetMaxOpenConns()方法用于设置与数据库的最大打开连接数.
2).创建表:
创建一个名为gorm_users的表.语句如下.
CREATE TABLE `gorm_users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`phone` longtext,
`name` longtext,
`password` longtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
注意:
这里创建的表也可以不用手动创建.定义好结构体后.调用db.AutoMigrate()方法即可按照结构创建对应的数据表.
Go
package main
import (
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
err = db.AutoMigrate(GormUser{})
if err != nil {
log.Fatal(err)
}
}
3).定义结构体:
sql
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
4).插入数据:
Gorm中db.Save()和db.Create()方法均可插入数据.根据构造好的结构体对象.直接调用db.Save()方法就可以插入一条记录.
示例:
Go
package main
import (
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
user := GormUser{
Phone: "10086",
Name: "ItB",
Password: "123456",
}
db.Save(&user)
db.Create(&GormUser{
Phone: "10087",
Name: "ItB2",
Password: "123456",
})
}
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
5).删除数据:
Gorm中删除数据一般先用db.Where()方法构造查询条件.在调用db.Delete()方法进行删除.
示例:
Go
package main
import (
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
var user = new(GormUser)
db.Where("phone = ?", "10086").Delete(&user)
}
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
6).查询数据:
Gorm中查询数据先用db.Where()方法构造查询条件.在使用db.Count()方法计算数量.如果要获取对象.则可以使用db.Find(&GormUser)来查询.如果只需要查一条记录.则可以使用db.First(&GormUser)来查询.
示例:
Go
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
var user = new(GormUser)
db.Where("phone = ?", "10087").Find(&user)
//db.First(&user, "phone = 10087")
fmt.Println(user)
}
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
7).更新数据:
Gorm中更新数据使用Update()方法.
示例:
Go
package main
import (
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
var user = new(GormUser)
db.Model(&user).Where("phone = ?", "10087").Update("phone", "10088")
}
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
8).错误处理:
Gorm中调用db.Error()方法就能获取到错误信息.
示例:
Go
package main
import (
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
var user = new(GormUser)
err = db.Model(&user).Where("phone = ?", "10087").Update("phone", "10088").Error
if err != nil {
log.Fatal(err)
}
}
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
9).事务处理:
Gorm中事务的处理也很简单.用db.Begin()方法声明开启事务.结束的时候调用tx.Commit()方法.异常的时候调用tx.Rollback()方法回滚.
示例:
Go
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
)
func main() {
dsn := "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
log.Fatal(err)
}
tx := db.Begin()
gormUser := GormUser{
Phone: "10089",
Name: "it3",
Password: "123456",
}
if err := tx.Create(&gormUser).Error; err != nil {
tx.Rollback()
fmt.Println(err.Error())
}
db.First(&gormUser, "phone = ?", "10089")
tx.Commit()
}
type GormUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
Beego ORM使用:
它支持Go语言中所有的类型存储.允许直接使用原生的Sql语句.采用CRUD风格能够轻松上手.进行表关联查询.并允许跨数据库兼容查询.在Beego中.数据库和Go语言对应的映射关系如下.
数据库的表(table) --> 结构体(struct)
记录(record,行数据) --> 结构体实例对象(object)
字段(field) --> 对象的属性(attribute)
1).定义表结构:
CREATE TABLE `beego_users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`phone` longtext,
`name` longtext,
`password` longtext,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2).定义模型:
Go
type BeegoUser struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
3).插入数据:
Go
package main
import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterModel(new(BeegoUsers))
}
func main() {
ormer := orm.NewOrm()
user := new(BeegoUsers)
user.Phone = "10086"
user.Password = "12345789"
fmt.Println(ormer.Insert(user))
}
type BeegoUsers struct {
ID uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
4).查询数据:
Go
package main
import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
"log"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterModel(new(BeegoUsers))
}
func main() {
user := BeegoUsers{}
user.Id = 1
ormer := orm.NewOrm()
err := ormer.Read(&user)
if err == orm.ErrNoRows {
log.Fatal("查询不到")
} else if err == orm.ErrMissPK {
log.Fatal("找不到主键")
} else {
fmt.Println(user.Id, user.Name)
}
}
type BeegoUsers struct {
Id uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
5).更新数据:
如果要更新数据.则先要给模型赋值.然后调用Update()方法即可.
Go
package main
import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterModel(new(BeegoUsers))
}
func main() {
user := BeegoUsers{}
user.Id = 1
user.Name = "it333"
ormer := orm.NewOrm()
num, err := ormer.Update(&user)
if err != nil {
fmt.Println("更新失败")
} else {
fmt.Println(num)
}
}
type BeegoUsers struct {
Id uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
6).删除数据:
删除数据首先要指定主键id.然后调用Delete()方法即可.
Go
package main
import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterModel(new(BeegoUsers))
}
func main() {
user := BeegoUsers{}
user.Id = 1
ormer := orm.NewOrm()
if num, err := ormer.Delete(&user); err != nil {
fmt.Println("删除失败")
} else {
fmt.Println(num)
}
}
type BeegoUsers struct {
Id uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
7).原生sql查询:
使用原生sql语句直接操作Raw()函数.返回一个RawSeter对象.用于对设置的Sql语句和参数进行操作.
Go
package main
import (
"fmt"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterModel(new(BeegoUsers))
}
func main() {
ormer := orm.NewOrm()
var result []orm.Params
num, err := ormer.Raw("select * from beego_users where id = ?", 1).Values(&result)
if err != nil {
fmt.Println(err)
}
fmt.Printf("查到 %d 行数据\n", num)
for i, row := range result {
fmt.Printf("第 %d 行: %#v\n", i+1, row)
}
}
type BeegoUsers struct {
Id uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
8)事务处理:
事务处理时.在Sql语句的开头调用Begin()方法.中间编写执行的Sql语句.最后判断如果有异常则执行Rollback()方法回滚.如果正常执行Commit()方法提交.
Go
package main
import (
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", "root:1234@tcp(127.0.0.1:3306)/test?charset=utf8")
orm.RegisterModel(new(BeegoUsers))
}
func main() {
ormer := orm.NewOrm()
user := new(BeegoUsers)
user.Id = 1
user.Name = "it1111"
user1 := new(BeegoUsers)
user1.Id = 12
user1.Name = "it222"
_, err := ormer.Update(user)
_, err1 := ormer.Insert(user1)
if err1 != nil || err != nil {
ormer.Rollback()
} else {
ormer.Commit()
}
}
type BeegoUsers struct {
Id uint64 `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
语雀地址https://www.yuque.com/itbosunmianyi/xg8vfe?
《Go.》 密码:xbkk 欢迎大家访问.提意见.