使用 GORM(Go 的 ORM 库)连接数据库,并实现增删改查操作,把实现过程整理成文章 | 青训营

76 阅读4分钟

1. Database/sql 的基本用法,设计原理,基础概念

什么是数据库?

  1. 数据库(Database, DB)是将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合
  2. 用来管理数据库的计算机系统称为数据库管理系统(Database Management System,DBMS)。
  3. 为什么DBMS那么重要?因为文本文件或Excel的局限性:
    1. 无法多人共享数据
    2. 无法提供操作大量数据所需的格式
    3. 实现读写自动化需要编程能力
    4. 无法应对突发事故
  4. DBMS的种类
    1. 层次数据库(Hierarchical Database, HDB):最古老的数据库之一,它把数据通过层次结构(树形结构)的方式表现出来。
    2. 关系数据库(Relational Database, RDB):关系数据库是现在应用最广泛的数据库。
    3. 面向对象数据库(Object Oriented Database, OODB):把数据以及对数据的操作集合起来以对象为单位进行管理。
    4. XML数据库(XML Database, XMLDB):XML 数据库可以对 XML 形式的大量数据进行高速处理。
    5. 键值存储系统(Key-Value Store, KVS):这是一种单纯用来保存查询所使用的主键(Key)和值(Value)的组合的数据库。

0401.jpg

什么是SQL?

SQL(Structured Query Language,结构化查询语言)是用来操作关系数据库的语言。

  1. SQL语句及其种类: SQL 用关键字、表名、列名等组合而成的一条语句(SQL 语句)来描述操作的内容。关键字是指那些含义或使用方法已事先定义好的英语单词,存在包含“对表进行查询”或者“参考这个表”等各种意义的关键字。根据对 RDBMS 赋予的指令种类的不同, SQL 语句可以分为以下三类。PS:实际使用的 SQL 语句当中有 90% 属于 DML。
    1. DDL(Data Definition Language,数据定义语言) 用来创建或者删除存储数据用的数据库以及数据库中的表等对象。 DDL 包含以下几种指令。
      1. CREATE: 创建数据库和表等对象
      2. DROP: 删除数据库和表等对象
      3. ALTER: 修改数据库和表等对象的结构
    2. DML(Data Manipulation Language,数据操纵语言) 用来查询或者变更表中的记录。 DML 包含以下几种指令。
      1. CREATE: 创建数据库和表等对象
      2. DROP: 删除数据库和表等对象
      3. ALTER: 修改数据库和表等对象的结构
    3. DCL(Data Control Language,数据控制语言) 用来确认或者取消对数据库中的数据进行的变更。除此之外,还可以对 RDBMS 的用户是否有权限操作数据库中的对象(数据库表等)进行设定。 DCL 包含以下几种指令。
      1. COMMIT: 确认对数据库中的数据进行的变更
      2. ROLLBACK: 取消对数据库中的数据进行的变更
      3. GRANT: 赋予用户操作权限
      4. REVOKE: 取消用户的操作权限
  2. SQL的基本书写规则:
    1. SQL语句要以分号(;)结尾;
    2. SQL语句不区分关键字大小写,插入表中的数据区分大小写;
    3. 常数的书写方式是固定的,字符串和日期常数需要使用单引号(')括起来,数字常数无需加注单引号(直接书写数字即可);
    4. 单词间需要用半角空格或者换行来分隔,不能使用全角空格作为单词的分隔符;

基本用法1

import driver 实现,使用driver + DSN 初始化 DB 连接;

执行一条SQL, 通过 rows 取回返回的数据 处理完毕,需要释放链接

设计原理

0402.png

DB 连接的几种类型:

直接连接 Conn; 预编译 Stmt; 事务 Tx;

处理返回数据的几种方式:

Exec - ExecContext - Result; Query - QueryContext - Rows(Columns); QueryRow- QueryRowContext - Row(Row 简化);

GORM

特性: 设计简介,功能强大,自由扩展的全功能ORM; 设计原则: API 简洁,测试优先,最小惊讶,灵活扩展,无依赖;功能完善:关联,事务,多数据库,字段权限,代码生成,多模式自由扩展等;

ORM (Object Relational Mapping):对象关系映射

结构体 和 SQL数据库存在映射;

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server;

MySQL

0403.png

表操作

package main

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

type User struct {

Id   int
Name string
Age  int
Addr string
Pic  string

}

func main() { // 用户名:密码@tcp(ip:port)/数据库?charset=utf8mb4&parseTime=True&loc=Local

dsn := "root:root123@tcp(127.0.0.1:3306)/test_gorm?charset=utf8mb4&parseTime=True&loc=Local"
    
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
	panic(err)
}
    

}

  1. GORM 实践

连接检查

package mysql

import ( "testing" "time" )

func TestStaleConnectionChecks(t *testing.T) { runTests(t, dsn, func(dbt *DBTest) { dbt.mustExec("SET @@SESSION.wait_timeout = 2")

	if err := dbt.db.Ping(); err != nil {
		dbt.Fatal(err)
	}

	// wait for MySQL to close our connection
	time.Sleep(3 * time.Second)

	tx, err := dbt.db.Begin()
	if err != nil {
		dbt.Fatal(err)
	}

	if err := tx.Rollback(); err != nil {
		dbt.Fatal(err)
	}
})

}

0405.png

连接检查设置

package mysql

import ( "errors" "io" "net" "syscall" )

var errUnexpectedRead = errors.New("unexpected read from socket")

func connCheck(conn net.Conn) error { var sysErr error

sysConn, ok := conn.(syscall.Conn)
if !ok {
	return nil
}
rawConn, err := sysConn.SyscallConn()
if err != nil {
	return err
}

err = rawConn.Read(func(fd uintptr) bool {
	var buf [1]byte
	n, err := syscall.Read(int(fd), buf[:])
	switch {
	case n == 0 && err == nil:
		sysErr = io.EOF
	case n > 0:
		sysErr = errUnexpectedRead
	case err == syscall.EAGAIN || err == syscall.EWOULDBLOCK:
		sysErr = nil
	default:
		sysErr = err
	}
	return true
})
if err != nil {
	return err
}

return sysErr

}

0406.png