golang gorm

ORM

ORM(Object Relational Mapping对象关系映射),其主要作用是在编程中,把面向对象的概念跟数据库中表的概念对应起来。举例来说就是,我定义一个对象,那就对应着一张表,这个对象的实例,就对应着表中的一条记录。对于数据来说,最重要最常用的是表:表中有列, orm就是将一张表映射成一个类,表中的列映射成类中的一个类。java 、python,但是针对go语言而言,struct,就是列如何映射,是因为列可以映射成struct中的类型,int->int,但是有另一个问题? 就是数据库中的列具备很好的描述性,但是struct有tag。执行sql, 需要我们有足够的sql语句基础、需要我们懂得不同的数据的sql。

常见的orm:
gorm
facebook开发的ent
sqlx

orm的优缺点

优点:

1提高了开发效率。

2屏蔽sql细节。可以自动对实体Entity对象与数据库中的Table进行字段与属性的映射;不用直接SQL编码

3屏蔽各种数据库之间的差异

缺点:

1orm会牺牲程序的执行效率和会固定思维模式

2太过依赖orm会导致sql理解不够

3对于固定的orm依赖过重,导致切换到其他的orm代价高

如何正确看待orm和sql之间的关系

1sql为主,orm为辅

2orm主要目的是为了增加代码可维护性和开发效率

连接
cpp 复制代码
import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  // refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
  dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
通过迁移生成表结构
cpp 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

type Product struct {
	gorm.Model
	Code  string
	Price uint
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&Product{})
}
简单的增删查改
c 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

type Product struct {
	gorm.Model
	Code  string
	Price uint
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second,   // 慢速 SQL 阈值
			LogLevel:                  logger.Silent, // 日志级别
			IgnoreRecordNotFoundError: true,          // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,          // 不要在 SQL 日志中包含参数
			Colorful:                  true,          // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&Product{})

	//create
	db.Create(&Product{Code: "D42", Price: 100})

	//read
	var product Product
	db.First(&product, 1) //根据整形主键查找
	// fmt.Println(product)
	db.First(&product, "code=?", "D42") //查找code=D42的记录

	//UPDATE
	db.Model(&product).Update("price", 200)
	//update多个字短
	db.Model(&product).Updates(Product{Price: 2000, Code: "F42"}) //仅更新非零值字段
	db.Model(&product).Updates(map[string]interface{}{"price": 2000, "code": "DD42"})
	fmt.Println(product)

	//Delete
	db.Delete(&product, 1)
}
通过NullString解决不能更新零值的问题

当updates函数传递的是结构体时,gorm只更新非零,在更新过程中可以通过传递仅包含个别字段的结构更新字段,就造成了不能直接通过设置各字段的默认值更新内容。解决仅更新非零值有两个解决方法:第一种指针形式,第二种sql.NulXXX

c 复制代码
package main

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

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

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

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second,   // 慢速 SQL 阈值
			LogLevel:                  logger.Silent, // 日志级别
			IgnoreRecordNotFoundError: true,          // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,          // 不要在 SQL 日志中包含参数
			Colorful:                  true,          // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&Product{})

	//create
	db.Create(&Product{Code: sql.NullString{"D42", true}, Price: 100})

	//read
	var product Product
	db.First(&product, 1) //根据整形主键查找
	// fmt.Println(product)
	db.First(&product, "code=?", "D42") //查找code=D42的记录

	//UPDATE
	db.Model(&product).Update("price", 200)
	//update多个字短
	db.Model(&product).Updates(Product{Price: 2000, Code: sql.NullString{"", true}}) //仅更新非零值字段
	// db.Model(&product).Updates(map[string]interface{}{"price": 2000, "code": "DD42"})
	fmt.Println(product)

	//Delete
	db.Delete(&product, 1)
}
表结构细节设计
c 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

type User struct {
	UserID uint   `gorm:"primarykey"`
	Name   string `gorm:"column:user_name;type:varchar(50);index:idx_user_name;unique;default:'bobby'"`
	// Code   sql.NullString
	// Price  uint
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second,   // 慢速 SQL 阈值
			LogLevel:                  logger.Silent, // 日志级别
			IgnoreRecordNotFoundError: true,          // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,          // 不要在 SQL 日志中包含参数
			Colorful:                  true,          // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&User{})

	db.Create(&User{})
}
create
cpp 复制代码
package main

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

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

type User struct {
	ID           uint           // Standard field for the primary key
	Name         string         // A regular string field
	Email        *string        // A pointer to a string, allowing for null values
	Age          uint8          // An unsigned 8-bit integer
	Birthday     *time.Time     // A pointer to time.Time, can be null
	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
	CreatedAt    time.Time      // Automatically managed by GORM for creation time
	UpdatedAt    time.Time      // Automatically managed by GORM for update time
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&User{})

	user := User{
		Name: "Bobby2",
	}
	result := db.Create(&user)
	fmt.Println(user.ID)
	fmt.Println(result.Error)
	fmt.Println(result.RowsAffected)
	//db.Model(&User{ID: 1}).Update("name", "")
}
批量插入
cpp 复制代码
package main

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

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

type User struct {
	ID           uint           // Standard field for the primary key
	Name         string         // A regular string field
	Email        *string        // A pointer to a string, allowing for null values
	Age          uint8          // An unsigned 8-bit integer
	Birthday     *time.Time     // A pointer to time.Time, can be null
	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
	CreatedAt    time.Time      // Automatically managed by GORM for creation time
	UpdatedAt    time.Time      // Automatically managed by GORM for update time
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&User{})

	var users = []User{
		{Name: "jinzhu1"},
		{Name: "jinzhu2"},
		{Name: "jinzhu3"},
	}
	//单一的sql语句
	// db.Create(&users)

	//为什么不一次性提交所有的?
	//sql语句有长度限制,需要分批提交
	db.CreateInBatches(users, 2)

	//for简单插入
	for _, user := range users {
		fmt.Println(user.ID)
	}

	// batch insert from `[]map[string]interface{}{}`
	db.Model(&User{}).Create([]map[string]interface{}{
		{"Name": "jinzhu_1", "Age": 18},
		{"Name": "jinzhu_2", "Age": 20},
	})
}
select
cpp 复制代码
package main

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

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

type User struct {
	ID           uint           // Standard field for the primary key
	Name         string         // A regular string field
	Email        *string        // A pointer to a string, allowing for null values
	Age          uint8          // An unsigned 8-bit integer
	Birthday     *time.Time     // A pointer to time.Time, can be null
	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
	CreatedAt    time.Time      // Automatically managed by GORM for creation time
	UpdatedAt    time.Time      // Automatically managed by GORM for update time
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&User{})

	//通过first查询单个数据(升序排序)
	// var user User
	// db.First(&user)
	// fmt.Println(user.ID)

	// 通过first查询单个数据(降序排序)
	// db.Last(&user)
	// fmt.Println(user)

	//通过主键查询
	// result := db.First(&user, 10)
	// if errors.Is(result.Error, gorm.ErrRecordNotFound) {
	// 	fmt.Println("未找到")
	// }
	// fmt.Println(user.ID)

	//通过主键查询
	// result := db.First(&user, "10")
	// if errors.Is(result.Error, gorm.ErrRecordNotFound) {
	// 	fmt.Println("未找到")
	// }
	// fmt.Println(user.ID)

	// //通过主键查询
	// result := db.First(&user, "abc")
	// if errors.Is(result.Error, gorm.ErrRecordNotFound) {
	// 	fmt.Println("未找到")
	// }
	// fmt.Println(user.ID)

	//通过主键查询
	// result := db.First(&user, []int{1, 3, 5, 13})
	// if errors.Is(result.Error, gorm.ErrRecordNotFound) {
	// 	fmt.Println("未找到")
	// }
	// fmt.Println(user.ID)

	//检索全部对象
	var users []User
	result := db.Find(&users)
	fmt.Println("总共影响了", result.RowsAffected)
	for _, user := range users {
		fmt.Println(user.ID)
	}
}
where条件查询
cpp 复制代码
package main

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

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

// type User struct {
// 	ID           uint           // Standard field for the primary key
// 	Name         string         // A regular string field
// 	Email        *string        // A pointer to a string, allowing for null values
// 	Age          uint8          // An unsigned 8-bit integer
// 	Birthday     *time.Time     // A pointer to time.Time, can be null
// 	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
// 	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
// 	CreatedAt    time.Time      // Automatically managed by GORM for creation time
// 	UpdatedAt    time.Time      // Automatically managed by GORM for update time
// }

// func main() {
// 	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
// 	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

// 	//日志配置
// 	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
// 	newLogger := logger.New(
// 		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
// 		logger.Config{
// 			SlowThreshold:             time.Second, // 慢速 SQL 阈值
// 			LogLevel:                  logger.Info, // 日志级别
// 			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
// 			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
// 			Colorful:                  true,        // 禁用颜色
// 		},
// 	)

// 	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
// 		Logger: newLogger,
// 	})
// 	if err != nil {
// 		fmt.Println(err)
// 	}

// 	//定义表结构
// 	//迁移 schema
// 	_ = db.AutoMigrate(&User{})

// 	var user User
// 	var users []User
// 	// db.Where("name=?", "jinzhu1").Find(&user)
// 	db.Where(&User{Name: "jinzhu1"}).Find(&user)
// 	db.Where(&User{Name: "jinzhu1"}).Find(&users)
// 	fmt.Println(user)
// 	fmt.Println(users)
// 	//string(拼sql)更灵活 最后
// 	//struct屏蔽变量名和表的字段的对应关系 最优先
// 	//map不灵活,但是可以解决strct屏蔽零值的问题 优先

// }
delete
cpp 复制代码
package main

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

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

type NewUser struct {
	ID           uint           // Standard field for the primary key
	Name         string         // A regular string field
	Email        *string        // A pointer to a string, allowing for null values
	Age          uint8          // An unsigned 8-bit integer
	Birthday     *time.Time     // A pointer to time.Time, can be null
	MemberNumber sql.NullString // Uses sql.NullString to handle nullable strings
	ActivatedAt  sql.NullTime   // Uses sql.NullTime for nullable time fields
	CreatedAt    time.Time      // Automatically managed by GORM for creation time
	UpdatedAt    time.Time      // Automatically managed by GORM for update time
	Deleted      gorm.DeletedAt
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	_ = db.AutoMigrate(&NewUser{})

	// var users = []NewUser{
	// 	{Name: "jinzhu1"},
	// 	{Name: "jinzhu2"},
	// 	{Name: "jinzhu3"},
	// }
	// db.Create(&users)

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

	//gorm软删除
	// db.Delete(&NewUser{}, 2)

	// var users []NewUser
	// result := db.Find(&users)
	// for _, user := range users {
	// 	fmt.Println(user.ID)
	// }
	// fmt.Println(result.RowsAffected)
	// fmt.Println(result.Error)

	//gorm硬删除
	db.Unscoped().Delete(&NewUser{}, 2)

	var users []NewUser
	result := db.Find(&users)
	for _, user := range users {
		fmt.Println(user.ID)
	}
	fmt.Println(result.RowsAffected)
	fmt.Println(result.Error)
}
关联表插入
cpp 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

// `User` belongs to `Company`, `CompanyID` is the foreign key
type User struct {
	gorm.Model
	Name      string
	CompanyID int
	Company   Company
}

type Company struct {
	ID   int
	Name string
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	//定义表结构
	//迁移 schema
	// _ = db.AutoMigrate(&User{})

	// db.Create(&User{
	// 	Name: "bobby",
	// 	Company: Company{
	// 		Name: "dslkjf",
	// 	},
	// })

	var user User
	// db.First(&user)
	// fmt.Println(user)

	//先查company_id,后查找user
	// db.Preload("Company").First(&user)
	//通过join语句查询
	db.Joins("Company").First(&user)
	fmt.Println(user)
}
hasmany关系
cpp 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

// User has many CreditCards, UserID is the foreign key
type User struct {
	gorm.Model
	CreditCards []CreditCard
}

type CreditCard struct {
	gorm.Model
	Number string
	UserID uint
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	// 定义表结构
	// 迁移 schema
	// _ = db.AutoMigrate(&CreditCard{})
	// _ = db.AutoMigrate(&User{})

	//在大型系统和高并发系统一般不使用外键约束,自己在业务层面保证数据的一致性,外键约束影响性能
	//外间约束可以保证数据的完整性
	user := User{}
	// db.Create(&user)
	// db.Create(&CreditCard{
	// 	Number: "12",
	// 	UserID: user.ID,
	// })
	// db.Create(&CreditCard{
	// 	Number: "34",
	// 	UserID: user.ID,
	// })

	db.Preload("CreditCards").First(&user)
	for _, card := range user.CreditCards {
		fmt.Println(card)
	}
}
manytomay
cpp 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

// User has and belongs to many languages, `user_languages` is the join table
type User struct {
	gorm.Model
	Languages []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
	gorm.Model
	Name string
}

func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	// 定义表结构
	// 迁移 schema
	// _ = db.AutoMigrate(&User{})

	// languages := []Language{}
	// languages = append(languages, Language{Name: "go"})
	// languages = append(languages, Language{Name: "java"})
	// user := User{
	// 	Languages: languages,
	// }
	// db.Create(&user)

	// var user User
	// db.Preload("Languages").First(&user)
	// for _, language := range user.Languages {
	// 	fmt.Println(language.Name)
	// }

	//关联模式
	var user User
	db.First(&user)
	var languages []Language
	//join查询
	db.Model(&user).Association("Languages").Find(&languages)
	fmt.Println(user.ID)
	fmt.Println(languages)
}
自定义表名

用于定义表名和统一的给所有的表名加一个前缀

定义表名(为结构体定义TableName方法)

c 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

type Language struct {
	gorm.Model
	Name string
}

// 在gorm中可以通过给某一个结构体添加TableName实现自定义表名
func (Language) TableName() string {
	return "my_language"
}
func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	// 定义表结构
	// 迁移 schema
	_ = db.AutoMigrate(&Language{})

}

添加统一的前缀(通过NamingStrategy添加表的前缀,不能与TableName同时存在,否在以TableName为准)

cpp 复制代码
package main

import (
	"fmt"
	"log"
	"os"
	"time"

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

type Language struct {
	gorm.Model
	Name string
}

// // 在gorm中可以通过给某一个结构体添加TableName实现自定义表名
//
//	func (Language) TableName() string {
//		return "my_language"
//	}
func main() {
	// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
	dsn := "root:root123456@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"

	//日志配置
	//设置全局的logger,这个logger在我们执行每个sql语句的时候会打印每一行sql
	newLogger := logger.New(
		log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
		logger.Config{
			SlowThreshold:             time.Second, // 慢速 SQL 阈值
			LogLevel:                  logger.Info, // 日志级别
			IgnoreRecordNotFoundError: true,        // 忽略记录器的 ErrRecordNotFound 错误
			ParameterizedQueries:      true,        // 不要在 SQL 日志中包含参数
			Colorful:                  true,        // 禁用颜色
		},
	)

	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		//添加前缀
		NamingStrategy: schema.NamingStrategy{
			TablePrefix: "maxshop_",
		},
		Logger: newLogger,
	})
	if err != nil {
		fmt.Println(err)
	}

	// 定义表结构
	// 迁移 schema
	_ = db.AutoMigrate(&Language{})

}
相关推荐
小叶学C++2 分钟前
【C++】类与对象(下)
java·开发语言·c++
ac-er88883 分钟前
PHP“===”的意义
开发语言·php
2401_854391085 分钟前
高效开发:SpringBoot网上租赁系统实现细节
java·spring boot·后端
Cikiss14 分钟前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
Cikiss15 分钟前
微服务实战——平台属性
java·数据库·后端·微服务
jk_10121 分钟前
MATLAB中decomposition函数用法
开发语言·算法·matlab
weixin_4640780722 分钟前
C#串口温度读取
开发语言·c#
无敌の星仔24 分钟前
一个月学会Java 第2天 认识类与对象
java·开发语言
OEC小胖胖29 分钟前
Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)
java·spring boot·后端·spring·mybatis·web
小小不董29 分钟前
《Linux从小白到高手》理论篇:深入理解Linux的网络管理
linux·运维·服务器·数据库·php·dba