这是我参与【第五届青训营】伴学笔记创作活动的第四天,此篇概述一下在青训营学习的go语言的数据库有关的知识。
Datebase/sql
-
基本用法:
-
数据库连接:
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello") -
数据库查询:
rows, err := db.Query("select id,name from users where id = ?", 1) if err != nil { // xxx } defer func() { // 后关闭,避免信息泄露 err = rows.Close() if err != nil {} } var users []user // 存储查询的结果 for rows.Next() { var user User err := rows.Scan(&user.Id, &user.Name) if err != nil { // xxx } users = append(users, user) } if rows.Err() != nil { // ... }
-
-
Driver 连接接口
// Driver接口 type Driver interface { // Open returns a new connection to the database. Open(name string) (Conn,error) } // Register makes a database driver available by the provided name. // If Register is called twice with the same name or if driver is nil, // it panics. func Register(name string,driver driver.Driver) { driversMu. Lock() defer driversMu.Unlock() if driver = nil { panic( "sql: Register driver is nil") } if _, dup := drivers[name]; dup { panic("sql: Register called twice for driver " + name) } drivers[name] = driver } // github . com/go-sql-driver/mysql/driver.go // 注册Driver func init { sql.Register("mysql",&MySQLDriver{}) } type Conn interface { // 返回与当前连接相关的执行SQL语句的准备状态,可以进行查询、删除等操作 Prepare(query string) (Stmt, error) // 关闭当前的链接,执行释放连接拥有的资源等清理工作 Close() error // 返回一个代表事务处理,通过它可以进行查询、更新等操作,或者对事务进行回滚、递交 Begin() (Tx, error) }
CRUD
-
基本用法
// 操作数据库 db.AutoMigrate(&Product) db.Migrator().CreateTable(&Product) // https://gorm.io/docs/migration.html //版本管理- https://github. com/go-gormigrate/gormigrate user := User{ Name: "Jinzhu", Age: 18,Birthday: time.Now(O)} result := db.Create(&user) // pass pointer of data to Create user.ID //返回主键 last insert id result.Error //返回 error result.RowsAffected //返回影响的行数 var users []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, { Name:"jinzhu3"}} db.Create(&users) db.CreateInBatches(users,100) -
基础概念
-
优点: gorm 可以连接多种数据库,只需要不同的驱动即可。官方目前仅支持 MySQL、PostgreSQL、SQlite、SQL Server 四种数据库,可以通过自定义的方式接入其他数据库。
-
连接代码
// MySQL 配置信息 username := "root" // 账号 password := "xxxxxx" // 密码 host := "127.0.0.2" // 地址 port := 3306 // 端口 DBname := "test" // 数据库名称 timeout := "10s" // 连接超时,10秒 dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, DBname, timeout) // Open 连接 db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect mysql.") } -
声明模型:
// 数据库代码 CREATE TABLE `gorm1`.`无标题` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `price` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = CREATE TABLE `gorm1`.`无标题` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL, `price` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic; // 对应的结构体 type Goods struct { // gorm.Model // 见下面的约定 Id int Name string Price int } -
约定:
-
gorm 制定了很多约定,并按照约定大于配置的思想工作, 比如会根据结构体的复数寻找表名,会使用 ID 作为主键,会根据 CreateAt、UpdateAt 和 DeletedAt 表示创建时间、更新时间和删除时间。
-
gorm 提供了一个 Model 结构体,可以将它嵌入到自己的结构体中
// 可实现软删除 type Model struct { ID uint `gorm:"primaryKey"` CreatedAt time.Time UpdatedAt time.Time DeletedAt gorm.DeletedAt `gorm:"index"` } -
字段标签 tag
// 设置 tag 来对该字段一些属性进行定义 type Post struct { Title string `gorm:"column:t, size:256, unique:true"` // 映射为 t,设置最大长度为 256,该字段唯一 }
-
-
-
自动迁移
在数据库的表尚未初始化时,gorm 可以根据指定的结构体自动建表。
-
自动创建表
type User struct { gorm.Model UserName string Password string } db.AutoMigrate(&User{})
-
-
创建数据
user := User{UserName: "123", Password: "haha"} result := db.Create(&user) // 插入后返回常用的插入数据,用user. 调用 , 如 user.ID // 通过 Select 选择指定字段, 只插入指定字段 result := db.Select("UserName").Create(&user) // 使用 Omit 方法过滤一些字段。 result := db.Omit("UserName").Create(&user) // 批量插入 users := []User{ {UserName: "123", Password: "aaa"}, {UserName: "234", Password: "bbb"}, {UserName: "345", Password: "ccc"}, } db.Create(&users) -
查询数据
-
查询单个数据: gorm 提供了 First、Take、Last 方法。它们都是通过
LIMIT 1来实现的,分别是主键升序、不排序和主键降序。user := User{} // 获取第一条记录(主键升序) db.First(&user) // SELECT * FROM users ORDER BY id LIMIT 1; // 如果没有查询到对象,会返回 ErrRecordNotFound 错误。 -
根据主键查询:
db.First(&user, 2001) // 也可以用 "2001" -
查询多个引用
users := []User{} result := db.Find(&users) // 可以通过访问返回值上的 Error 和 RowsAffected 字段获取异常和影响的行号 -
where 条件
db.Where("name <> ?", "wangming").Find(&users)传递 Struct、Map 和 切片时,可以实现更简便的设置条件
db.Where(map[string]interface{}{"user_name": "wang", "password": "123"}).Find(&user) -
其他操作
// 排序 Order Order("no desc, password") // 分组 Group Having // Save 方法更新所有字段,即使是零值也会更新 db.Save(&user) // 使用 Model 和 Update 方法更新单列 db.Model(&user).Update("user_name", "haha") // 删除 db.Where().Delete(&user) db.Delete(&User{}, 20) 根据主键删除 // 特殊用法 db.Model(&User{Id: 111})..Update("age", gorm.Expr("age * ? + ?", 2, 100))
-