Go语言ORM框架-GORM

数据库ORM

ORM基本概念

Object Relation Mapping(关系对象映射) 把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中 在具体的操作实体对象的时候,不需要直接与复杂的 SQL语句打交道,只需简单的操作实体对象的属性和方法

Go语言ORM框架-GORM_第1张图片  

表 => struct

列 => struct 属性

行数据 => struct 对象

数据操作 => struct 对象方法的调用/函数的调用 

Gorm

介绍

Gorm是使用go语言开发的ORM库

下载

地址: github.com/jinzhu/gorm 

入门

Go语言ORM框架-GORM_第2张图片

示例

package main

import (
	"fmt"
	"os"
	"time"

	_ "github.com/jinzhu/gorm/dialects/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()
	db.LogMode(true)
	// 自动迁移数据库
	db.AutoMigrate(&User{})

	// 插入数据
	for i := 0; i < 10; i++ {
		db.Create(&User{Name: fmt.Sprintf("wu_%d", i), Password: "123!@#"})
	}

	// 按主键获取数据
	var u User
	db.First(&u, 1)
	fmt.Println(u)

	// 按条件获取数据
	var u2 User
	db.First(&u2, "name = ?", "wu_7")
	fmt.Println(u2)

	// 更新数据
	db.Model(u2).Update("password", "!@#QWE")
	fmt.Println(u2)

	// 删除数据
	db.Delete(&u2)
	fmt.Println(u2)
}

驱动

数据库驱动

MySQL驱动

驱动:github.com/go-sql-driver/mysql

导入:github.com/jinzhu/gorm/dialects/mysql

连接设置 username:password@protocol(host:port)/dbname?charset=utf8mb4&loc=Asia%2FShanghai 为处理Time类型若设置loc为Local, 需要设置parseTime=true

Go语言ORM框架-GORM_第3张图片

迁移

自动迁移

自动迁移数据库到最新版本

只会添加列和索引,不会修改列类型和删除列

示例

package main

import (
	"fmt"
	"os"
	"time"

	_ "github.com/jinzhu/gorm/dialects/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()
	db.LogMode(true)
	// 自动迁移数据库
	db.AutoMigrate(&User{})

}

判断表是否存在

package main

import (
	"fmt"
	"os"
	"time"

	_ "github.com/jinzhu/gorm/dialects/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()
    // 判断表是否存在
    fmt.Println(db.HasTable(&User{}))

    // 通过表名判断表是否存在
    fmt.Println(db.HasTable("users"))
}

创建表

package main

import (
	"fmt"
	"os"
	"time"

	_ "github.com/jinzhu/gorm/dialects/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()
	db.CreateTable(&User{})
}

删除表

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()
	// 删除表
	db.DropTable(&User{})

	// 通过表名删除表
	db.DropTable("user")

	// 当表不存在时跳过删除
	db.DropTableIfExists(&User{})
}

修改列

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()

	// 修改列的类型
	db.Model(&User{}).ModifyColumn("birthday", "datetime")
}

删除列

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()

	// 删除列
	db.Model(&User{}).DropColumn("status")
}

外键

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	gorm.Model
	Name     string
	Password string
	Birthday time.Time
	Desc     string
	Status   int
}

type Addr struct {
	gorm.Model
	City string
	Street string
	UserId uint
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()

	db.CreateTable(&Addr{})
	// 添加外键
	db.Model(&Addr{}).AddForeignKey("user_id", "users(id)", "RESTRICT", "RESTRICT")
}

添加索引

	// 添加索引
	db.Model(&User{}).AddIndex("idx_birthday", "birthday")
	db.Model(&User{}).AddIndex("idx_city_street", "city", "street")

添加唯一索引

	// 添加唯一索引
	db.Model(&User{}).AddUniqueIndex("idx_name", "name")
	db.Model(&User{}).AddUniqueIndex("idx_city_user_id", "city", "user_id")

删除索引

	// 删除索引
	db.Model(&User{}).RemoveIndex("idx_name")
	db.Model(&User{}).RemoveIndex("idx_birthday")
	db.Model(&User{}).RemoveIndex("idx_city_street")
	db.Model(&User{}).RemoveIndex("idx_city_user_id")

模型

标签

名称:gorm

常用属性

column:设置列名

type:类型

primary_key:主键

AUTO_INCREMENT: 自增长

unique: 唯一

not null: 不允许为NULL

default:默认值

index: 索引

gorm.Model

属性

ID

CreatedAt

UpdatedAt

DeletedAt

方法 func (m Model) TableName() string 设置表名

示例

Go语言ORM框架-GORM_第4张图片

CURD

创建

package main

import (
	"fmt"
	"os"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	gorm.Model
	Name     string
	Password string `gorm:"default:'123!@#'"` // 设置默认值
}

// 定义回调函数,在创建之前执行
func (u *User) BeforeCreate(scope *gorm.Scope) error {
	fmt.Println("before create")
	return nil
}
func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()

	u := User{Name: "wu"}
	fmt.Println(db.newRecord(u)) // 判断对象是否已经被创建

	db.Create(&u)
	fmt.Println(db.newRecord(u))
}

查找

基本查找

package main

import (
	"fmt"
	"os"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	gorm.Model
	Name     string
	Password string `gorm:"default:'123!@#'"` // 设置默认值
}

func main() {
	// 获取数据库连接
	db, err := gorm.Open("mysql", "root:1234@tcp(192.168.204.130:3306)/testorm?charset=utf8mb4&parseTime=true&loc=PRC")
	if err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
	// 延迟关闭数据库连接
	defer db.Close()
	db.DropTableIfExists("users")
	db.AutoMigrate(&User{})
	for i := 0; i < 10; i++ {
		u := User{Name: fmt.Sprintf("wu_%d", i)}
		if err := db.Create(&u).Error; err != nil {
			fmt.Println(err)
		}
	}

	// 获取第一条数据
	var u01 User
	db.First(&u01)
	fmt.Println(u01)

	// 获取最后一条数据
	var u02 User
	db.Last(&u02)
	fmt.Println(u02)

	// 按主键获取
	var u03 User
	db.First(&u03, 8)
	fmt.Println(u03)

	// 按条件查询一条
	var u04 User
	db.First(&u04, "name=?", "wu_5")
	fmt.Println(u04)

	// 获取所有数据
	var us User
	db.Find(&us)
	fmt.Println(us)

	db.Find(&us, "name != ?", "wu_5")
	fmt.Println(us)
}

where条件

Go语言ORM框架-GORM_第5张图片

 not条件

Go语言ORM框架-GORM_第6张图片

 or条件

Go语言ORM框架-GORM_第7张图片

 查询结果(指定列)

Go语言ORM框架-GORM_第8张图片

 排序(order)

Go语言ORM框架-GORM_第9张图片

 分页(offset&limit)

Go语言ORM框架-GORM_第10张图片

 数量(count)

Go语言ORM框架-GORM_第11张图片

 指定表名

Go语言ORM框架-GORM_第12张图片 聚合(集合)

Go语言ORM框架-GORM_第13张图片

 原始SQL

 联查

	db = db.Table("users").Select("users.name, addresses.city, addresses.street")
	rows, _ := db.Joins("left join addresses on users.id = addresses.user_id").Rows()
	for rows.Next() {
		var name, city, street, string
		rows.Scan(&name, &city, &street)
		fmt.Println(name, city, street)
	}

更新

全部更新

	var u User
	if err := db.First(&u).Error; err == nil {
		u.Name = "wu123"
		u.Password = "123!@#"
		db.Save(u)
	} else {
		fmt.Println(err)
	}

批量更新

	db.Model(&User{}).Where("name like ?", "%3%").Update("password", "123!@#")

	// 不会执行Callback更新update_at字段
	db.Table("users").Where("name like ?", "%4%").UpdateColumn("password", "123123")
	db.Model(&User{}).Where("name like ?", "%5%").UpdateColumn(User{Name: "xxxxxx", Password: "123123"})

	// 只会更新指定字段
	db.Table("users").Where("name like ?", "%6%").Updates(map[string]interface{}{"password": "xxx", "name": "yyy"})

	// 只会更新更改和非零值的字段
	db.Model(&User{}).Where("name like ?", "%7%").Updatees(User{Name: "ccc", Password: "aaaa"})

表达式更新

	db.Model(&User{}).Update("password", gorm.Expr("md5(password)"))

删除

单记录删除

	var u User
	if err := db.First(&u).Error; err == nil {
		db.Delete(&u)
	} else {
		fmt.Println(err)
	}

批量更新

	db.Where("name like ?", "%5%").Delete(User{})

永久更新

	db.Unscoped().Where("name like ?", "%6%").Delete(User{})

原始SQL

原始SQL执行

更新

db.Exec

查询

db.Raw(sql).Scan(&rt)

db.Raw(sql).Row()

db.Raw(sql).Rows()

回调

创建

BeforeSave

BeforeCreate

AfterCreate

AfterSave

更新

BeforeSave

BeforeUpdate

AfterUpdate

AfterSave

删除

BeforeDelete

AfterDelete

查找

AfterFind 

错误&日志

错误

db.Error

db.GetErrors()

db.RecordNotFound()

日志

db.LogMode(true)

db.Debug().Where()

db.SetLogger()

事务

tx := db.Begin()

tx.Create()

tx.Rollback()

tx.Commit()

项目练习

todolist

修改todolist使用数据库

登陆

task 增加/删除/修改/查询

Go语言ORM框架-GORM

1.ORM的前世今生

object relation mapping

Go语言ORM框架-GORM_第14张图片

2.Go语言如何连接数据库

安装mysql

navicat连接数据库

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  dsn := "root:1234@tcp(127.0.0.1:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
  if err != nil {
      panic(err)
  }
  fmt.Println("连接成功...")
}

3.如何通过结构体生成表结构

orm_test\main.go

package main

import (
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

func main() {
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
	err = db.AutoMigrate(&model.Product{})
	if err != nil {
		panic(err)
	}
}

 orm_test\model\product.go

package model

import "gorm.io/gorm"

type Product struct {
	gorm.Model
	Code   string
	Price uint
}
PS D:\Workspace\Go\src\projects\orm_test> go run main.go
连接成功...

2023/05/13 21:32:01 D:/Workspace/Go/src/projects/orm_test/main.go:37
[0.507ms] [rows:-] SELECT DATABASE()

2023/05/13 21:32:01 D:/Workspace/Go/src/projects/orm_test/main.go:37
[3.914ms] [rows:1] SELECT SCHEMA_NAME from Information_schema.SCHEMATA where SCHEMA_NAME LIKE 'orm_test%' ORDER BY SCHEMA_NAME='orm_test' DESC,SCHEMA_NAME limit 1

2023/05/13 21:32:01 D:/Workspace/Go/src/projects/orm_test/main.go:37
[11.688ms] [rows:-] SELECT count(*) FROM information_schema.tables WHERE table_schema = ? AND table_name = ? AND table_type = ?

2023/05/13 21:32:01 D:/Workspace/Go/src/projects/orm_test/main.go:37
[68.744ms] [rows:0] CREATE TABLE `products` (`id` bigint unsigned AUTO_INCREMENT,`created_at` datetime(3) NULL,`updated_at` datetime(3) NULL,`deleted_at` datetime(3) NULL,`code` longtext,`prince` bigint unsigned,PRIMARY KEY (`id`),INDEX `idx_products_deleted_at` (`deleted_at`))

4.数据库的基本操作-增删改查

添加

package main

import (
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
}

func main() {
	db.Create(&model.Product{Code: "D42", Price: 200})
}

查找

func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product
	db.First(&p, 1)
	fmt.Println(p.Code)
}
func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product
	// db.First(&p, 1)
	// fmt.Println(p.Code)
	db.First(&p, "code=?", "D42")
	fmt.Println(p.Price)
}

更新

func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product
	db.First(&p, "code=?", "D42")
	fmt.Println(p.Price)
	db.Model(&p).Update("price", 300)
}
func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product

	db.First(&p, 2)

	db.Model(&p).Updates(model.Product{
		Code:  "FF42",
		Price: 600,
	})
	db.First(&p, 2)
	fmt.Println(p.Code)
	fmt.Println(p.Price)
}
PS D:\Workspace\Go\src\projects\orm_test> go run main.go
连接成功...

2023/05/13 21:58:00 D:/Workspace/Go/src/projects/orm_test/main.go:47
[4.424ms] [rows:0] SELECT * FROM `products` WHERE `products`.`id` = ? AND `products`.`deleted_at` IS NULL ORDER BY `products`.`id` LIMIT 1

2023/05/13 21:58:00 D:/Workspace/Go/src/projects/orm_test/main.go:49 WHERE conditions required
[1.063ms] [rows:0] UPDATE `products` SET `updated_at`=?,`code`=?,`price`=? WHERE `products`.`deleted_at` IS NULL

2023/05/13 21:58:00 D:/Workspace/Go/src/projects/orm_test/main.go:53
[6.741ms] [rows:0] SELECT * FROM `products` WHERE `products`.`id` = ? AND `products`.`deleted_at` IS NULL ORDER BY `products`.`id` LIMIT 1
FF42
600
func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product

	db.First(&p, 2)

	// db.Model(&p).Updates(model.Product{
	// 	Code:  "FF42",
	// 	Price: 600,
	// })
	// db.First(&p, 2)
	// fmt.Println(p.Code)
	// fmt.Println(p.Price)

	// 零值 string "" int 0
	db.Model(&p).Updates(model.Product{
		Code:  "FF42",
		Price: 0,
	})
	db.First(&p, 2)
	fmt.Println(p.Code)
	fmt.Println(p.Price)
}
func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product

	db.First(&p, 2)

	db.Model(&p).Updates(map[string]interface{}{
		"Code":  "",
		"Price": 0,
	})
	db.First(&p, 2)
	fmt.Println(p.Code)
	fmt.Println(p.Price)
}

删除

func main() {
	// db.Create(&model.Product{Code: "D42", Prince: 200})

	var p model.Product

	db.First(&p, 2)

	// delete ... from xxx where id=111 100元->80元
	// 软删除 flag status, 0或1 0不显示, 1显示,当删除的时候就把flag字段update为0,查询的时候,选择flag=1的记录
	// 商城后台,是有权限查看任何记录,delete_at填充值不为null
	db.Delete(&p, 2)
}

5.Gorm更新零值的第二种解决方案

D:\Workspace\Go\src\projects\orm_test\model\product.go

package model

import (
	"database/sql"

	"gorm.io/gorm"
)

type Product struct {
	gorm.Model
	Code  sql.NullString
	Price uint
}

D:\Workspace\Go\src\projects\orm_test\main.go

package main

import (
	"database/sql"
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
}

func main() {
	db.Create(&model.Product{
		Code:  sql.NullString{String: "D6666", Valid: true},
		Price: 8888,
	})
}
func main() {
	// db.Create(&model.Product{
	// 	Code:  sql.NullString{String: "D6666", Valid: true},
	// 	Price: 8888,
	// })

	var p model.Product
	db.First(&p, 3)
	fmt.Println(p.Code)

	db.Model(&p).Updates(model.Product{
		Code:  sql.NullString{"", true},
		Price: 9999,
	})
}

6.如何使用Gorm的Tag

https://gorm.io/zh_CN/docs/models.html

D:\Workspace\Go\src\projects\orm_test\model\product.go

package model

import (
	"database/sql"

	"gorm.io/gorm"
)

type Product struct {
	gorm.Model
	Code  sql.NullString
	Price uint
}

type Food struct {
	FoodId uint   `gorm:"primarykey"`
	Name   string `gorm:"column:food_name;type:varchar(32);index:idx_food_name,unique"`
}
package main

import (
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
	db.AutoMigrate(&model.Food{})
}

func main() {
}

 7.避坑-update更新默认值

package main

import (
	"database/sql"
	"fmt"
	"log"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
	db.AutoMigrate(&User{})
}

type User struct {
	ID           uint
	Name         string
	Email        *string
	Age          uint8
	Birthday     *time.Time
	MemberNumber sql.NullString
	ActivatedAt  sql.NullTime
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

func main() {
	now := time.Now()
	u1 := User{Name: "欢喜", Birthday: &now}
	result := db.Create(&u1)
	fmt.Println(u1.ID)
	fmt.Println(result.Error)
	fmt.Println(result.RowsAffected)
}
package main

import (
	"database/sql"
	"fmt"
	"log"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
}

type User struct {
	ID           uint
	Name         string
	Email        *string
	Age          uint8
	Birthday     *time.Time
	MemberNumber sql.NullString
	ActivatedAt  sql.NullTime
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

func main() {

	db.Model(&User{ID: 2}).Update("Name", "")
}
db.Model(&User{ID: 2}).Updates(User{Name: ""})
	s := "[email protected]"
	db.Model(&User{ID: 2}).Updates(User{Email: &s})
	s := ""
	db.Model(&User{ID: 2}).Updates(User{Email: &s})

8.批量添加数据有几种方法

type User struct {
	ID           uint
	Name         string
	Email        *string
	Age          uint8
	Birthday     *time.Time
	MemberNumber sql.NullString
	ActivatedAt  sql.NullTime
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

func main() {
	// 第一种
	users := []User{
		{Name: "wu123"},
		{Name: "ku123"},
		{Name: "zu123"},
		{Name: "xu123"},
		{Name: "lu123"},
	}
	db.Create(users)
	for _, user := range users {
		fmt.Println(user.ID)
	}
}
func main() {
	// 第一种
	users := []User{
		{Name: "wu123"},
		{Name: "ku123"},
		{Name: "zu123"},
		{Name: "xu123"},
		{Name: "lu123"},
	}
	// 第二种
	db.CreateInBatches(users, 2)

	for _, user := range users {
		fmt.Println(user.ID)
	}
}
func main() {
	users := []User{
		{Name: "wu123"},
		{Name: "ku123"},
		{Name: "zu123"},
		{Name: "xu123"},
		{Name: "lu123"},
	}
	// 第三种
	db.Model(User{}).Create([]map[string]interface{}{
		{"Name": "wu123"},
		{"Name": "ku123"},
		{"Name": "zu123"},
		{"Name": "xu123"},
		{"Name": "lu123"},
	})

	for _, user := range users {
		fmt.Println(user.ID)
	}
}

9.查询记录的几种方式

D:\Workspace\Go\src\projects\orm_test\model\model.go

package model

import (
	"database/sql"
	"time"
)

type User struct {
	ID           uint
	Name         string
	Email        *string
	Age          uint8
	Birthday     *time.Time
	MemberNumber sql.NullString
	ActivatedAt  sql.NullTime
	CreatedAt    time.Time
	UpdatedAt    time.Time
}
package main

import (
	"errors"
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
}

func main() {
	u1 := model.User{}
	r := db.First(&u1)
	fmt.Println(u1.ID)
	fmt.Println(r.Error)
	fmt.Println(r.RowsAffected)
	b := errors.Is(r.Error, gorm.ErrRecordNotFound)
	if b {
		fmt.Println("查无此人")
	} else {
		fmt.Println("他是"+u1.Name)
	}
}
func main() {

	u2 := model.User{}
	db.Take(&u2)
	fmt.Println(u2.ID)
}

通过主键查询 

func main() {
	u3 := model.User{}
	r2 := db.First(&u3, 4)
	fmt.Println(u3.Name)
	fmt.Println(r2)

}

多个主键ID

func main() {
	u3 := model.User{}
	r2 := db.First(&u3, 2,3,4)
	fmt.Println(u3.Name)
	fmt.Println(u3.ID)
	fmt.Println(r2)

}
func main() {
	var users []model.User
	r3 := db.Find(&users, []int{2,3,4})
	fmt.Println(r3)
	for _, user := range users{
		fmt.Println(user.Name)
	}

}
func main() {
	// 主键写错成字符串,还能查询吗?能
	u3 := model.User{}
	r2 := db.First(&u3, "3")
	fmt.Println(u3.Name)
	fmt.Println(r2)
}

10.带条件的查询

func main() {
	u1 := model.User{}
	db.Where("name=?", "wu123").First(&u1)
	fmt.Println(u1.ID)

	u2 := model.User{}
	db.Where(model.User{Name: "wu123"}).First(&u2)
	fmt.Println(u2.ID)

}
func main() {
	var users []model.User
	db.Where("name <> ?", "wu123").Find(&users)
	for _, item := range users {
		fmt.Println(item.ID)
	}
}
func main() {
	var userList []model.User
	db.Where(map[string]interface{}{"name": "wu123"}).Find(&userList)
	for _, item := range userList {
		fmt.Println(item.ID)
	}
}
func main() {
	var userList2 []model.User
	db.Where(map[string]interface{}{
		"name": "wu123",
		"age": 0,
	}).Find(&userList2)
	for _, item := range userList2 {
		fmt.Println(item.ID)
	}
}

11.多种更新操作

单列更新 

func main() {
	// ErrMissingWhereClause
	db.Model(&model.User{}).Where("name=?", "wu123").Update("age", 18)
}
	u1 := model.User{}
	db.First(&u1, 3)
	fmt.Println(u1.Name)
	db.Model(&u1).Update("email", "[email protected]")
	u2 := model.User{}
	db.First(&u2, 4)
	db.Model(&u2).Where("name=?", "ku123").Update("age", 18)

多列更新

func main() {
	u3 := model.User{}
	db.First(&u3, 4)
	db.Model(&u3).Updates(model.User{Name: "zu123", Age: 17})

}
func main() {
	u4 := model.User{}
	db.First(&u4, 5)
	db.Model(&u4).Updates(map[string]interface{}{
		"name": "lu123",
		"age":  18,
	})

}
func main() {
	u5 := model.User{}
	db.First(&u5, 5)
	db.Model(&u5).Select("name").Updates(map[string]interface{}{
		"name": "zzz",
		"age": 16,
	})

}
func main() {
	u6 := model.User{}
	db.First(&u6, 7)
	db.Model(&u6).Omit("name").Updates(map[string]interface{}{
		"name": "zzz",
		"age": 16,
	})

}
func main() {
	u7 := model.User{}
	db.First(&u7, 7)
	db.Model(&u7).Select("name", "age").Updates(map[string]interface{}{
		"name": "zzz",
		"age": 0,
	})

}

12.真删除还是假删除

添加商品 

func main() {
	// delete
	// soft delete delete_at
	p1 := model.Product{
		Code: sql.NullString{
			String: "nu123",
			Valid: true,
		},
		Price: 99,
	}

	p2 := model.Product{
		Code: sql.NullString{
			String: "ku123",
			Valid: true,
		},
		Price: 99,
	}

	var productList []model.Product

	productList = append(productList, p1)
	productList = append(productList, p2)

	db.CreateInBatches(productList, 2)
}
func main() {
	// delete
	// soft delete delete_at
	var p model.Product
	db.First(&p, 6)
	db.Delete(&p)
}
func main() {
	// delete
	// soft delete delete_at
	var p model.Product
	db.First(&p, 6)
	db.Delete(&p)

	db.Where("price=?", 666).Delete(model.Product{})
}

https://gorm.io/zh_CN/docs/delete.html

13.如何添加有依赖关系的数据

关联插入

D:\Workspace\Go\src\projects\orm_test\model\model.go

package model

import (
	"gorm.io/gorm"
)

type Employer struct {
	gorm.Model
	Name      string
	CompanyID int
	Company   Company
}

type Company struct {
	gorm.Model
	Name string
}
package main

import (
	"database/sql"
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
	ab.AutoMigrate(&model.Company{})
	ab.AutoMigrate(&model.Employer{})
}

func main() {
	// 关联插入,表与表,多个
	c1 := model.Company{
		Name: "wu123",
	}
	e1 := model.Employer{
		Name: "qu123",
		Company: c1,
	}
	db.Create(&e1)
}

14.如何查询有依赖关系的数据

func main() {
	var e1 model.Employer
	db.First(&e1)
	fmt.Println(e1.Name)
	fmt.Println(e1.Company.ID)
	fmt.Println(e1.Company.Name)
}
func main() {
	var e1 model.Employer

	db.Preload("Company").First(&e1)
	fmt.Println(e1.Name)
	fmt.Println(e1.Company.ID)
	fmt.Println(e1.Company.Name)
}
func main() {

	var e2 model.Employer
	db.Joins("Company").First(&e2)
	fmt.Println(e2.Name)
	fmt.Println(e2.Company.ID)
	fmt.Println(e2.Company.Name)
}
	var e2 model.Employer
	db.Joins("Company").First(&e2, 2)
	fmt.Println(e2.Name)
	fmt.Println(e2.Company.ID)
	fmt.Println(e2.Company.Name)

15.一对多关系的数据添加和查询

D:\Workspace\Go\src\projects\orm_test\model\model.go

package model

import (
	"gorm.io/gorm"
)

type Employer struct {
	gorm.Model
	Name      string
	CompanyID int
	Company   Company
    CreditCards []CreaditCard 
}

type Company struct {
	gorm.Model
	Name string
}

type CreaditCard struct {
	gorm.Model
	Number string
	EmployerId uint
}
package main

import (
	"fmt"
	"log"
	"projects/orm_test/model"

	"os"
	"time"

	"github.com/google/uuid"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var db *gorm.DB

func init() {
	var err error
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // Slow SQL threshold
			LogLevel:                  logger.Info, // Log level
			IgnoreRecordNotFoundError: true,        // Ignore ErrRecordNotFound error for logger
			ParameterizedQueries:      true,        // Don't include params in the SQL log
			Colorful:                  true,        // Disable color
		},
	)

	// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
	dsn := "root:1234@tcp(192.168.204.130:3306)/orm_test?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("连接成功...")
	db.AutoMigrate(&model.CreaditCard{})
}

func main() {
	// has many
	var e1 model.Employer
	db.First(&e1, 1)
	for i := 0; i < 5; i++ {
		id := uuid.New()
		c := model.CreaditCard{
			Number: id.String(),
			EmployerId: e1.ID,
		}
		db.Create(&c)
	}
}
func main() {
	// has many
	var e1 model.Employer
	db.First(&e1, 1)

	// 第一种模式查询
	db.Preload("CreditCards").First(&e1)
	for _, card := range e1.CreditCards {
		fmt.Println(card.Number)
	}
}
func main() {
	// has many
    // 关联方式查询
	var e1 model.Employer
	db.First(&e1, 1)

	var CreditCards []model.CreditCard
	db.Model(&e1).Association("CreditCards").Find(&creditCards)
	for _, card := range creditCards {
		fmt.Println(card.Number)
	}
}

你可能感兴趣的:(golang,对象关系映射,ORM框架)