Go中使用GORM操作SQLite数据库

Go中使用GORM操作SQLite数据库

GORM 是一个使用广泛的 Golang ORM 类库。

SQLite 是一种C语言库,它实现了一个 小型 , 快速 , 自包含 , 高可靠性 , 功能齐全 的 SQL数据库引擎。

GORM 2.0 完全从零开始,引入了一些不兼容的 API 变更和许多改进。

  • (1) GORM 的开发已经迁移至 github.com/go-gorm ,import 路径也修改为 gorm.io/gorm
  • (2) 数据库驱动被拆分为独立的项目。比如:github.com/go-gorm/sqlite ,它的 import 路径变更为 gorm.io/driver/sqlite
  • (3) 支持字段权限:只读、只写、只创建、只更新、忽略
  • (4) 更好的自定义类型支持(例如: JSON)
  • … …

前期准备

查看 go 当前版本:

1
2
$ go version
go version go1.16.5 darwin/amd64

查看 sqlite3 当前版本:

1
2
3
$ sqlite3 --version
3.32.2 2020-06-04 12:58:43
ec02243ea6ce33b090870ae55ab8aa2534b54d216d45c4aa2fdbb00e86861e8c

创建项目

(1) 创建一个名为 go-gorm-sqlite 的目录,并使用 go mod 进行依赖包管理。

1
2
3
4
5
6
$ mkdir go-gorm-sqlite

$ cd go-gorm-sqlite

$ go mod init go-gorm-sqlite
go: creating new go.mod: module go-gorm-sqlite

该操作后,会生成 go.mod 文件,类似于 node 的 package.json 文件。

使用 cat 命令查看该文件内容如下:

1
2
3
4
$ cat go.mod 
module go-gorm-sqlite

go 1.16

(2) 编写个 hello world 代码,保证环境可以跑通。

创建 main.go 文件:

1
2
# 使用 vi 命令编辑
$ vi main.go

文件 main.go 代码如下:

1
2
3
4
5
6
7
8
9
10
package main

import (
"fmt"
)

func main() {
fmt.Println("==> Hello,World!")
}

运行代码:

1
2
$ go run main.go 
==> Hello,World!

安装 gorm 包

使用 go get 进行 gorm 包的安装。

这一步需要引入两个库,一个是 gorm 主库,一个是 sqlite 数据库驱动 (若使用其他数据库,则需要引入其他的驱动)。

1
2
3
4
5
6
$ go get -u gorm.io/gorm
go get: added gorm.io/gorm v1.21.11

$ go get -u gorm.io/driver/sqlite
go get: added github.com/mattn/go-sqlite3 v1.14.7
go get: added gorm.io/driver/sqlite v1.1.4

可以看到 gorm 的 sqlite 驱动,底层使用的还是 mattn/go-sqlite3 库。

再查看一下 go.mod 文件,已经多了 require () 部分,指明引入了哪些包。

1
2
3
4
5
6
7
8
9
10
$ cat go.mod                     
module go-gorm-sqlite

go 1.16

require (
github.com/mattn/go-sqlite3 v1.14.7 // indirect
gorm.io/driver/sqlite v1.1.4 // indirect
gorm.io/gorm v1.21.11 // indirect
)

编写代码

这里的代码参考 gorm 文档。

修改 main.go 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

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

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

func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}

// Migrate the schema
db.AutoMigrate(&Product{})

// 插入内容
db.Create(&Product{Title: "新款手机", Code: "D42", Price: 1000})
db.Create(&Product{Title: "新款电脑", Code: "D43", Price: 3500})

// 读取内容
var product Product
db.First(&product, 1) // find product with integer primary key
db.First(&product, "code = ?", "D42") // find product with code D42

// 更新操作: 更新单个字段
db.Model(&product).Update("Price", 2000)

// 更新操作: 更新多个字段
db.Model(&product).Updates(Product{Price: 2000, Code: "F42"}) // non-zero fields
db.Model(&product).Updates(map[string]interface{}{"Price": 2000, "Code": "F42"})

// 删除操作:
db.Delete(&product, 1)
}

代码里定义了一个 Product 结构体,对应 sqlite 数据库里的 products 表。

使用 go run 来运行代码:

1
$ go run main.go 

运行结束后,查看当前目录,发现项目里会多一个 test.db 文件,就是生产的 sqlite 数据库文件。

1
2
3
4
5
6
7
8
9
$ ls -al 
total 56
drwxr-xr-x 7 wang staff 224 7 11 13:12 .
drwxr-xr-x 8 wang staff 256 7 11 12:56 ..
-rw-r--r-- 1 wang staff 2308 7 11 13:11 README.md
-rw-r--r-- 1 wang staff 170 7 11 13:05 go.mod
-rw-r--r-- 1 wang staff 1070 7 11 13:05 go.sum
-rw-r--r-- 1 wang staff 990 7 11 13:12 main.go
-rw-r--r-- 1 wang staff 12288 7 11 13:12 test.db

使用 sqlite3 命令查看数据库

在终端中直接使用 sqlite3 + 数据库文件名,可以直接进入数据库提示符界面(如果数据库不存在会直接创建新的数据库)。

在sqlite3提示符界面,SQLite命令已点号(.)开头,比如:

.databases 列出数据库的名称(数据库文件路径)。
.tables 列出数据库里的表。
.schema {表名} 列出表的建表语句。
.indices {表名} 列出表的索引名称。
.exit 退出 SQLite 提示符。
.quit 退出 SQLite 提示符。

以下是操作实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ sqlite3 test.db 
SQLite version 3.32.2 2020-06-04 12:58:43
Enter ".help" for usage hints.

sqlite> .databases
main: /Users/wang/Code/gospace/go-demos/go-gorm-sqlite/test.db

sqlite> .tables
products

sqlite> .schema products
CREATE TABLE `products` (
`id` integer,`created_at` datetime,
`updated_at` datetime,
`deleted_at` datetime,
`title` text,
`code` text,
`price` integer,
PRIMARY KEY (`id`)
);
CREATE INDEX `idx_products_deleted_at` ON `products`(`deleted_at`);

sqlite> .indices products
idx_products_deleted_at

sqlite> .header on
sqlite> .mode list
sqlite> SELECT * FROM products;
id|created_at|updated_at|deleted_at|title|code|price
1|2021-07-11 13:12:42.867814+08:00|2021-07-11 13:12:42.871312+08:00
|2021-07-11 13:12:42.872189+08:00|新款手机|F42|2000

sqlite> .mode line
sqlite> SELECT * FROM products;
id = 1
created_at = 2021-07-11 13:12:42.867814+08:00
updated_at = 2021-07-11 13:12:42.871312+08:00
deleted_at = 2021-07-11 13:12:42.872189+08:00
title = 新款手机
code = F42
price = 2000

参考内容

https://gorm.io/docs/index.html
https://www.runoob.com/sqlite/sqlite-select.html
https://my.oschina.net/wangyongtao/blog/5127208