goland 数据库操作 | 青训营笔记

241 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第5篇笔记

快速上手

import (
   "database/sql"
   "encoding/json"
   "fmt"
   _ "github.com/go-sql-driver/mysql"
   "os"
)
​
type User struct {
   User_id       uint   `json:"user_id"`
   User_name     string `json:"user_name"`
   User_password string `json:"user_password"`
}
​
func main() {
   db, err := sql.Open("mysql", "root:qzzx91112@tcp(127.0.0.1:3306)/douyin")
   rows, err := db.Query("select * from `user` where `user_name` = ?", "chz")//自带防止sql注入
   if err != nil {
      fmt.Fprintf(os.Stdout, "%v", err)
   }
   defer rows.Close() //再结束时关闭,rows相当于游标
   var users []User
   for rows.Next() {
      var user User
      err := rows.Scan(&user.User_id, &user.User_name, &user.User_password)
      if err != nil {
         panic(err)
      }
      users = append(users, user)
   }
   for _, user := range users {
      user_json, err := json.Marshal(user)
      if err != nil {
         panic(err)
      }
      err = json.Unmarshal(user_json, &user)//第二个参数需要以指针格式传输
      if err != nil {
         panic(err)
      }
      fmt.Printf("%v", user)
   }
}

执行过程

  1. 连接数据库

    使用sql.Open(driverName,dataSourceName)

    • driverName:数据库名
    • dataSourceName:DSN格式为username:password@protocol(address)/dbname?param=value

    连接时会从drivers中找到对于数据库的驱动,然后执行OpenConnector(DSN)解析DSN并加载到db中。

image-20220516000551797.png

image-20220516001630340.png image-20220516001554833.png

使用`mysql.NewConnector(mysql.Config{})`连接数据库

```
connector, err := mysql.NewConnector(&mysql.Config{
        User:      "user",
        Passwd:    "pasword",
        Net:       "protocol",
        Addr:      "address",
        DBName:    "databasename",
        ParseTime: true,
    })
```
  1. 数据操作(CRUD)

    func CRUD(){
        rows, err := db.Query("select * from `user` where `user_name` = ?", "陈鹤中")
        if err != nil {
            fmt.Fprintf(os.Stdout, "%v\n", err)
        }
        defer rows.Close() //再结束时关闭,rows相当于游标
        var users []User
        for rows.Next() {
            var user User
            err := rows.Scan(&user.User_id, &user.User_name, &user.User_password)
            if err != nil {
                panic(err)
            }
            users = append(users, user)
        }
        r, _ := db.Exec("delete from `user` where `user_name`=?", "test"+strconv.Itoa(i))
            id, _ := r.RowsAffected()
            fmt.Println("\ndelete succ:", id)
        r, _ := db.Exec("insert into `user` values (null,?,?)", "test"+strconv.Itoa(i), "test_pwd")
                id, _ := r.LastInsertId()
                fmt.Println("\ninsert succ:", id)
        r, _ := db.Exec("update `user` set `user_password`=? where `user_name`=?", "password", "test"+strconv.Itoa(i))
                ar, _ := r.RowsAffected()
                fmt.Println("\nupdate succ:", ar)
    }
    

    事务操作

    • DB.Begin() 开启事务
    • DB.Commit() 提交事务
    • DB.Rollback() 事务回滚
    func (){
    conn, _ := db.Begin()
            for i := 0; i < 10; i++ {
                r, err := db.Exec("insert into `user` values (null,?,?)", "test"+strconv.Itoa(i), "test_pwd")
                if err != nil{
                    conn.Rollback()
                    break
                }
                id, _ := r.LastInsertId()
                fmt.Println("\ninsert succ:", id)
            }
            conn.Commit()
    }
    

使用gorm操作数据库

Why gorm?

  • 全特性 ORM (几乎包含所有特性)
  • 模型关联 (一对一, 一对多,一对多(反向), 多对多, 多态关联)
  • 钩子 (Before/After Create/Save/Update/Delete/Find)
  • 预加载
  • 事务
  • 复合主键
  • SQL 构造器
  • 自动迁移
  • 日志
  • 基于GORM回调编写可扩展插件
  • 全特性测试覆盖
  • 开发者友好

gorm安装

go get -u github.com/jinzhu/gorm

使用gorm实现CRUD

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
​
//使用gorm时,结构体的首字母要大写
type User struct {
    gorm.Model
    User_name     string
    User_password string
}
​
func main() {
    db, err := gorm.Open(mysql.Open("root:qzzx91112@tcp(127.0.0.1:3306)/douyin_utf8?parseTime=True"))
    //在mysql中的日期时间字段时string类型,如果转到`timeTime`类型,需要在代码中用`time.Parse`进行转化
    if err != nil {
        panic("failed to connect database")
    }
​
    //操作数据库
    db.AutoMigrate(&User{})
    //db.Migrator().CreateTable(&User{}) //创建表
​
    myuser := User{
        User_name:     "myusername",
        User_password: "mypassword",
    }
    // 增
    db.Create(&myuser)
    users := make([]User, 3)
    for i := 0; i < 2; i++ {
        users[i] = User{
            User_name:     "myusername",
            User_password: "mypassword",
        }
    }
    //db.Where("user_name = ?", "myusernname").First(&users) 查询多条数据
    fmt.Printf("User:%v is created\n", myuser)
    // 查
    var user User
    db.First(&user, "user_name = ?", "myusername")
    fmt.Printf("User:%v is selected\n", user)
    // 改
    db.Model(&user).Update("user_password", "new_password")
    fmt.Printf("User:%v is update to latest\n", user)
    // 删 -
    db.Delete(&user)
    fmt.Println("User is deleted", user)
}

Gorm标签

例:

type User struct {
  gorm.Model
  Name         string
  Age          sql.NullInt64
  Birthday     *time.Time
  Email        string  `gorm:"type:varchar(100);unique_index"`
  Role         string  `gorm:"size:255"` //设置字段的大小为255个字节
  MemberNumber *string `gorm:"unique;not null"` // 设置 memberNumber 字段唯一且不为空
  Num          int     `gorm:"AUTO_INCREMENT"` // 设置 Num字段自增
  Address      string  `gorm:"index:addr"` // 给Address 创建一个名字是  `addr`的索引
  IgnoreMe     int     `gorm:"-"` //忽略这个字段
}
标签说明
Column指定列的名称
Type指定列的类型
Size指定列的大小,默认是 255
PRIMARY_KEY指定一个列作为主键
UNIQUE指定一个唯一的列
DEFAULT指定一个列的默认值
PRECISION指定列的数据的精度
NOT NULL指定列的数据不为空
AUTO_INCREMENT指定一个列的数据是否自增
INDEX创建带或不带名称的索引,同名创建复合索引
UNIQUE_INDEX类似 索引,创建一个唯一的索引
EMBEDDED将 struct 设置为 embedded
EMBEDDED_PREFIX设置嵌入式结构的前缀名称
-忽略这些字段
标签说明
MANY2MANY指定连接表名称
FOREIGNKEY指定外键
ASSOCIATION_FOREIGNKEY指定关联外键
POLYMORPHIC指定多态类型
POLYMORPHIC_VALUE指定多态的值
JOINTABLE_FOREIGNKEY指定连接表的外键
ASSOCIATION_JOINTABLE_FOREIGNKEY指定连接表的关联外键
SAVE_ASSOCIATIONS是否自动保存关联
ASSOCIATION_AUTOUPDATE是否自动更新关联
ASSOCIATION_AUTOCREATE是否自动创建关联
ASSOCIATION_SAVE_REFERENCE是否引用自动保存的关联
PRELOAD是否自动预加载关联