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 当前版本:

$ go version
go version go1.16.5 darwin/amd64

查看 sqlite3 当前版本:

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

创建项目

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

$ 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 命令查看该文件内容如下:

$ cat go.mod 
module go-gorm-sqlite

go 1.16

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

创建 main.go 文件:

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

文件 main.go 代码如下:

package main

import (
    "fmt"
)

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

运行代码:

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

安装 gorm 包

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

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

$ 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 () 部分,指明引入了哪些包。

$ 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 文件:

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 来运行代码:

$ go run main.go 

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

$ 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 提示符。

以下是操作实例:

$ 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