GORM SQLite 教程:快速入门与实践 – wiki基地

GORM SQLite 教程:快速入门与实践

GORM(Go Object Relational Mapper)是 Golang 语言中最流行的 ORM 库之一,它提供了便捷的方式来连接和操作各种数据库,极大地简化了数据库操作的复杂性。SQLite 是一种轻量级的嵌入式数据库,它无需独立的服务器进程,直接将数据库存储在文件中,方便部署和携带。 本文将结合 GORM 和 SQLite,深入讲解如何使用 GORM 连接 SQLite 数据库,进行数据模型的定义、CRUD(创建、读取、更新、删除)操作、迁移、高级查询等,并通过实践案例,帮助你快速上手 GORM 和 SQLite 的开发。

一、准备工作

在开始之前,确保你已经安装了以下软件:

  • Go: 确保你的 Go 版本是 1.13 或更高。可以从 https://golang.org/dl/ 下载安装。
  • 文本编辑器或 IDE: 例如 VS Code, GoLand 等。
  • (可选)SQLite 数据库管理工具: 例如 DB Browser for SQLite。 它可以帮助你可视化地查看和管理 SQLite 数据库。

二、安装 GORM 和 SQLite Driver

打开你的终端,进入你的 Go 项目目录,并使用以下命令安装 GORM 和 SQLite driver:

bash
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite

这两个命令会下载并安装 GORM 的核心库和 SQLite 的 driver。 driver 负责 GORM 与 SQLite 数据库之间的连接和通信。

三、连接 SQLite 数据库

首先,创建一个 main.go 文件,并添加以下代码:

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 后续代码将在此处添加

}
“`

这段代码的作用如下:

  • 导入必要的包: 导入了 fmt (用于打印输出), log (用于错误处理), gorm.io/gorm (GORM 的核心库) 和 gorm.io/driver/sqlite (SQLite driver)。
  • gorm.Open() 函数: 使用 gorm.Open() 函数连接 SQLite 数据库。sqlite.Open("test.db") 指定了数据库文件的路径和名称。如果文件不存在,GORM 会自动创建它。 &gorm.Config{} 提供了一些配置选项,例如日志记录、连接池大小等。 你可以根据需要进行配置。
  • 错误处理: 检查连接是否成功。如果连接失败,程序会打印错误信息并退出。
  • 成功连接提示: 如果连接成功,会打印一条消息到控制台。

运行 go run main.go,如果一切顺利,你应该会看到 “Connected to SQLite database successfully!” 的消息。 同时,你的项目目录下会生成一个名为 test.db 的 SQLite 数据库文件。

四、定义数据模型

接下来,我们需要定义 Go 结构体来映射数据库表。 例如,我们定义一个 Product 结构体:

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique" // 数据库code字段加上唯一索引
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 迁移 schema
db.AutoMigrate(&Product{})

// 后续代码将在此处添加

}
“`

这段代码新增了以下内容:

  • Product 结构体: 定义了一个 Product 结构体,它包含了 ID, CreatedAt, UpdatedAt, DeletedAt (来自 gorm.Model)、CodePrice 字段。
    • gorm.Model: GORM 提供的默认模型,包含 ID(主键)、CreatedAt(创建时间)、UpdatedAt(更新时间)、DeletedAt(删除时间)。
    • Code: 商品代码,类型为字符串。 gorm:"index:idx_code,unique" 是一个 GORM tag,它指定了在数据库中为 Code 字段创建一个名为 idx_code 的唯一索引。 唯一索引保证了 Code 字段的值在表中是唯一的。
    • Price: 商品价格,类型为无符号整数。
  • db.AutoMigrate(&Product{}): 使用 AutoMigrate() 函数自动创建数据库表。 GORM 会根据 Product 结构体的定义,在数据库中创建一个名为 products 的表。 如果表已经存在,GORM 会自动更新表的 schema,以匹配结构体的定义。 注意: AutoMigrate 在生产环境中应该谨慎使用,因为它可能会导致数据丢失。 更好的做法是使用数据库迁移工具,手动编写 SQL 脚本来更新 schema。

再次运行 go run main.go,GORM 会自动创建 products 表。 你可以使用 SQLite 数据库管理工具来查看表的结构。

五、CRUD 操作

现在,我们可以开始进行 CRUD 操作了。

1. 创建 (Create)

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique" // 数据库code字段加上唯一索引
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 迁移 schema
db.AutoMigrate(&Product{})

// 创建一个 Product
product := Product{Code: "D42", Price: 100}
result := db.Create(&product) // 通过数据的指针来创建

if result.Error != nil {
    log.Fatal("Failed to create product:", result.Error)
}

fmt.Println("Created product with ID:", product.ID)
fmt.Println("Affected rows:", result.RowsAffected)

}
“`

这段代码新增了以下内容:

  • 创建 Product 实例: 创建了一个 Product 结构体的实例,设置了 Code 为 “D42” 和 Price 为 100。
  • db.Create(&product): 使用 db.Create() 函数将 product 插入到数据库中。 注意: 需要传递结构体指针 &product,GORM 会自动填充 ID, CreatedAt, UpdatedAt 等字段。
  • 结果处理: db.Create() 函数返回一个 *gorm.DB 对象,包含了操作的结果信息。 result.Error 存储了错误信息,result.RowsAffected 存储了受影响的行数。 我们检查 result.Error,如果发生错误,打印错误信息并退出。 否则,打印新创建的 product 的 ID 和受影响的行数。

运行 go run main.go,你会在数据库的 products 表中看到一条新的记录。

2. 读取 (Read)

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique" // 数据库code字段加上唯一索引
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 迁移 schema
db.AutoMigrate(&Product{})

// 创建一个 Product (如果数据库为空)
var count int64
db.Model(&Product{}).Count(&count)
if count == 0 {
    product := Product{Code: "D42", Price: 100}
    db.Create(&product)
}

// 读取 Product
var product Product
result := db.First(&product, 1) // 根据 ID 查询
// result := db.Where("code = ?", "D42").First(&product) // 根据 Code 查询

if result.Error != nil {
    log.Fatal("Failed to find product:", result.Error)
}

fmt.Println("Found product:", product)

}
“`

这段代码新增了以下内容:

  • 查询 Product: 使用 db.First(&product, 1) 根据 ID 查询 ID 为 1 的 Product。 或者,可以使用 db.Where("code = ?", "D42").First(&product) 根据 Code 查询 Code 为 “D42” 的 Product。 db.First()db.Where().First() 都会将查询结果填充到 product 变量中。
  • 结果处理: 检查 result.Error,如果发生错误,打印错误信息并退出。 否则,打印查询到的 product 的信息。
  • 创建Product (如果数据库为空): db.Model(&Product{}).Count(&count) 查询 Product 表有多少条记录,如果数据库是空的,就插入一条记录,保证可以查询到内容,方便测试。

运行 go run main.go,你会看到查询到的 Product 的信息。

3. 更新 (Update)

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique" // 数据库code字段加上唯一索引
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 迁移 schema
db.AutoMigrate(&Product{})

// 创建一个 Product (如果数据库为空)
var count int64
db.Model(&Product{}).Count(&count)
if count == 0 {
    product := Product{Code: "D42", Price: 100}
    db.Create(&product)
}

// 更新 Product
var product Product
db.First(&product, 1)

product.Price = 200
result := db.Save(&product) // 保存更改

if result.Error != nil {
    log.Fatal("Failed to update product:", result.Error)
}

fmt.Println("Updated product:", product)

}
“`

这段代码新增了以下内容:

  • 更新 Price: 首先查询 ID 为 1 的 Product,然后修改 product.Price 的值为 200。
  • db.Save(&product): 使用 db.Save() 函数保存更改。 db.Save() 会更新数据库中与 product 匹配的记录。

运行 go run main.go,你会看到 Product 的 Price 已经被更新为 200。

4. 删除 (Delete)

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique" // 数据库code字段加上唯一索引
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 迁移 schema
db.AutoMigrate(&Product{})

// 创建一个 Product (如果数据库为空)
var count int64
db.Model(&Product{}).Count(&count)
if count == 0 {
    product := Product{Code: "D42", Price: 100}
    db.Create(&product)
}

// 删除 Product
var product Product
db.First(&product, 1)

result := db.Delete(&product) // 删除

if result.Error != nil {
    log.Fatal("Failed to delete product:", result.Error)
}

fmt.Println("Deleted product")

}
“`

这段代码新增了以下内容:

  • db.Delete(&product): 使用 db.Delete() 函数删除与 product 匹配的记录。 db.Delete() 默认会执行物理删除,即从数据库中永久删除记录。

运行 go run main.go,你会发现 ID 为 1 的 Product 已经被删除。

六、高级查询

GORM 提供了丰富的高级查询功能,例如:

  • 条件查询: 使用 Where() 函数指定查询条件。
  • 排序: 使用 Order() 函数指定排序规则。
  • 分页: 使用 Limit()Offset() 函数实现分页。
  • 预加载: 使用 Preload() 函数预加载关联数据。
  • 原生 SQL: 使用 Raw() 函数执行原生 SQL 查询。

以下是一个使用条件查询、排序和分页的示例:

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique" // 数据库code字段加上唯一索引
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“test.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}

fmt.Println("Connected to SQLite database successfully!")

// 迁移 schema
db.AutoMigrate(&Product{})

// 创建一些 Product (如果数据库为空)
var count int64
db.Model(&Product{}).Count(&count)
if count == 0 {
    db.Create(&Product{Code: "D42", Price: 100})
    db.Create(&Product{Code: "D43", Price: 200})
    db.Create(&Product{Code: "D44", Price: 150})
}

// 高级查询
var products []Product
result := db.Where("price > ?", 120).
    Order("price DESC").
    Limit(2).
    Offset(0).
    Find(&products)

if result.Error != nil {
    log.Fatal("Failed to find products:", result.Error)
}

fmt.Println("Found products:", products)

}
“`

这段代码查询 Price 大于 120 的 Product,按照 Price 降序排序,每页显示 2 条记录,显示第一页的结果。

七、实践案例:简单的商品管理系统

我们可以将 GORM 和 SQLite 应用到一个简单的商品管理系统中。 该系统可以实现以下功能:

  • 添加商品
  • 删除商品
  • 修改商品信息
  • 查询商品列表

完整的代码实现会比较长,这里只提供一个框架,你需要根据自己的需求完善代码。

“`go
package main

import (
“fmt”
“log”

"gorm.io/driver/sqlite"
"gorm.io/gorm"

)

type Product struct {
gorm.Model
Code string gorm:"index:idx_code,unique"
Price uint
}

func main() {
db, err := gorm.Open(sqlite.Open(“products.db”), &gorm.Config{})
if err != nil {
log.Fatal(“Failed to connect to database:”, err)
}
db.AutoMigrate(&Product{})

for {
    fmt.Println("1. 添加商品")
    fmt.Println("2. 删除商品")
    fmt.Println("3. 修改商品信息")
    fmt.Println("4. 查询商品列表")
    fmt.Println("5. 退出")

    var choice int
    fmt.Print("请选择操作:")
    fmt.Scanln(&choice)

    switch choice {
    case 1:
        // 添加商品
    case 2:
        // 删除商品
    case 3:
        // 修改商品信息
    case 4:
        // 查询商品列表
    case 5:
        fmt.Println("退出系统")
        return
    default:
        fmt.Println("无效的选择")
    }
}

}
“`

八、总结

本文详细介绍了如何使用 GORM 连接 SQLite 数据库,进行数据模型的定义、CRUD 操作、迁移、高级查询等。 通过学习本文,你应该能够快速上手 GORM 和 SQLite 的开发,并能够将它们应用到实际项目中。 GORM 提供了强大的功能和灵活的配置,可以帮助你简化数据库操作,提高开发效率。 SQLite 则以其轻量级和易用性,成为小型项目和嵌入式系统的理想选择。 希望本文能够帮助你更好地理解和使用 GORM 和 SQLite。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部