设计模式之 Database/SQL 与 GORM 实践 | 青训营笔记

90 阅读4分钟

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

1. 理解database/sql

对于现在的服务来说,数据库作为不可或缺的一部分,在所有的数据库中,在Go语言当中,database/sql只是一套统一的抽象的接口,真正与数据库打交道的是各个数据库对应的驱动实现,在使用时需要先注册对应驱动,然后就可以使用sql中定义的接口统一操作数据库。

1.基本用法

最开始我们需要通过导入database/sql的包才能进行我们的数据库的连接,然后通过导入我们所需要的驱动。这样我们所需要的包就准备完毕了。

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
)

接下来我们需要通过sql包中的Open方法来将我们的方法来对其进行连接。获取数据库连接与返回的错误,如果存在错误就进行判断处理,最后使用完毕后将连接进行关闭

import ( 
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
)
func main() {
	db, err := sql.Open("mysql",
		"user:password@tcp(127.0.0.1:3306)/hello")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()
        err = db.Ping()
        if err != nil {
	     // do something here
        }
}

以上就是利用database/sql进行mysql数据库连接的简单代码。

2.设计原理

在Go语言当中database/sql的设计原理如下图所示

image.png

我们通过图就可以发现应用程序通过操作接口来连接database/sql包,包又通过对接口的操作来连接数据库

2.GORM基础使用

1.基本用法

假定我们已经通过grom连接到数据库,并且返回了数据库连接变量为db。

1.Create

对于创建一条数据,我们最熟悉的就是Create,同样,在grom当中,我们同样可以通过Create,我们可以直接通过以下代码,对数据表进行插入或者创建新数据的操作

db.Create(&User{Name:"Tom" , Age:18 , CreateAt:time.Now()})

以上这一代码其实也等同于下面这个操作

user := User{Name: "Tom" , Age: 18 , CreateAt: time.Now()}
db.Select( "Name" , "Age" , "CreatedAt" ).Create(&user) 

我们也可以通过Select进行选定User当中的元素后进行创建新元素。

2.Query

GORM 提供FirstTake,Last方法从数据库中检索单个对象,它在查询数据库时添加条件,如果没有找到记录LIMIT 1将返回错误。ErrRecordNotFound

// 获取按主键排序的第一条记录 
db.First(&user)  
// SELECT * FROM users ORDER BY id LIMIT 1;  

// 获取一条记录,无指定顺序 
db.Take(&user)  
// SELECT * FROM users LIMIT 1;  

// 获取最后一条记录,按主键排序 desc  
db.Last(&user)  
// SELECT * FROM users ORDER BY id DESC LIMIT 1;  
result := db.First(&user) result.RowsAffected 

//返回找到的记录数 
result.Error         
// 返回错误或 nil  
// 检查错误 ErrRecordNotFound errors.Is  (result.Error, gorm.ErrRecordNotFound)

3.Update

1.保存所有字段 Save

Save 会保存所有的字段,即使字段是零值

db.Save(&user)

2.更新单个列

当使用 Update 更新单个列时,你需要指定条件,否则会返回 ErrMissingWhereClause 错误

// 条件更新
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")\
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;\

// User 的 ID 是 `111`
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;

// 根据条件和 model 的值进行更新
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;

3.更新多列

Updates 方法支持 struct 和 map[string]interface{} 参数。当使用 struct 更新时,默认情况下,GORM 只会更新非零值的字段

// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;
// 根据 `map` 更新属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

4.Delete

1.删除一条记录

删除一条记录时,删除对象需要指定主键,否则会触发批量删除,例如:

// Email 的 ID 是 `10` 
db.Delete(&email) 
// DELETE from emails where id = 10;  
// 带额外条件的删除 
db.Where("name = ?", "jinzhu").Delete(&email) 
// DELETE from emails where id = 10 AND name = "jinzhu"; 

2.根据主键删除

GORM 允许通过主键(可以是复合主键)和内联条件来删除对象,它可以使用数字(如以下例子。也可以使用字符串——译者注)。

db.Delete(&User{}, 10) 
// DELETE FROM users WHERE id = 10;  
db.Delete(&User{}, "10") 
// DELETE FROM users WHERE id = 10;  
db.Delete(&users, []int{1,2,3}) 
// DELETE FROM users WHERE id IN (1,2,3);