golang轻量级SQLite数据库ORM功能插件库ormlite的使用

golang轻量级SQLite数据库ORM功能插件库ormlite的使用

ormlite是一个轻量级的包,实现了类似ORM的功能和SQLite数据库的辅助工具。

Model

该包操作符合Model接口的模型。任何结构体如果有存储数据的表,我们就称之为模型。

type Model interface {
    Table() string
}

CRUD

该包提供了一系列函数来创建、读取、更新和删除数据。

QueryStruct

从表中加载数据并扫描到提供的结构体中。如果查询范围太广加载了多行数据,将扫描最后一行。此函数还支持加载关系(将在下面描述)。

type SimpleStruct struct {
  IntField int64 `ormlite:"col=rowid,primary"`
  Text string
  UnusedField bool `ormlite:"-"`
}

var s SimpleStruct
err := QueryStruct(db, "", nil, &s)

示例中使用的标签说明:

  • col - 指定自定义列名扫描到字段
  • primary - 表示模型主键,主要用于保存模型时
  • - - 对包隐藏字段,使其不受任何影响

QuerySlice

与QueryStruct非常相似,只是它将多行数据加载到切片中。

Upsert

此函数用于保存或更新现有模型。如果模型有primary字段且其值为零,则此模型将被插入到模型的表中。否则,模型的记录将根据其当前值更新(不包括has-one关系)。此函数还支持更新相关模型,但不包括创建或编辑many-to-many相关模型。

err := Upsert(db, &s)

Insert

用于插入模型的函数。与Upsert不同,它在约束错误时返回错误。

Delete

此函数…是的,它使用主键值从数据库中删除模型。如果模型没有主键或其值为零,将返回错误。由于有时了解删除操作是否真的在数据库中发生很有用,该函数将检查受影响的行数,如果行数不为正,则返回特殊的ErrNoRowsAffected

Options

type Options struct {
   // 添加where子句到查询
   Where         Where    
   Limit         int      
   Offset        int      
   OrderBy       *OrderBy 
   // 加载关系到指定深度,
   // 如果深度为0则不加载任何关系
   RelationDepth int      
}

对于大多数查询,使用DefaultOptions()就足够了,它的关系深度为1。

如果已经有包含Options的变量,可以使用以下函数扩展它们:

  • WithLimit
  • WithOffset
  • WithOrder
  • WithWhere

例如:

opts := ormlite.WithWhere(ormlite.DefaultOptions(), ormlite.Where{"id": 1})

Relations

QueryStruct、QuerySlice和Upsert支持加载模型之间的关系,支持的关系类型有:

  • Has One
  • Has Many
  • Many To Many

由于可以控制加载关系的深度,因此不必担心循环加载。但有几种标签可以配置关系。

Has One

type Model struct {
   Related ormlite.Model `ormlite:"has_one,col=related_model_id"`
}
  • has_one 表示此字段代表与其他模型的has one关系类型
  • col 是一个可选参数,用于指定相关模型外键的自定义列名

Has Many

type Model struct {
   Related []ormlite.Model `ormlite:"has_many"`
}
  • has_many 是唯一表示has many关系的参数,但要求相关模型必须有primary字段

Many To Many

type Model struct {
  Related       []ormlite.Model `ormlite:"many_to_many,table=mapping_table,field=model_id"`
  RelatedActive []ormlite.Model `ormlite:"many_to_many,table=mapping_table(active=1),field=model_id"`
}
  • many_to_many 表示字段代表多对多关系
  • table(附加条件) 应包含映射表名以检索关系信息。如果需要使用附加条件映射实体,可以在括号中指定描述它们的sql。目前只支持一个附加字段
  • field 应指定映射表中具有原始模型外键的列

还有一个要求是相关模型的主键字段必须包含ref设置,该设置指定其在映射表中的外键列名。

通过相关项搜索

有时通过相关项搜索多对多模型很有用,因此运行以下代码:

type Author struct {
    Id     int      `ormlite:"primary,ref=author_id"`
    Topics []*Topic `ormlite:"many_to_many,table=author_topics,field=author_id"`
    Name   string
}

func (a *Author) Table() string { return "authors" }

type Topic struct {
    Id      int       `ormlite:"primary,ref=topic_id"`
    Authors []*Author `ormlite:"many_to_many,table=author_topics,field=topic_id"`
    Content string
}

func (p *Topic) Table() string { return "topics" }

func main() {
    db, err := sql.Open("sqlite3", ":memory:?_fk=1")
    if err != nil {
        panic(err)
    }

    _, err = db.Exec(`
       create table authors(id integer primary key, name text);
       create table topics(id integer primary key, content text, author_id int);
       create table author_topics(author_id integer, topic_id integer);
    `)
    if err != nil {
        panic(err)
    }

    john := &Author{Name: "John"}
    err = ormlite.Upsert(db, john)
    if err != nil {
        panic(err)
    }

    pete := &Author{Name: "Pete"}
    err = ormlite.Upsert(db, pete)
    if err != nil {
        panic(err)
    }

    cars := &Topic{Content: "Cars", Authors: []*Author{john, pete}}
    err = ormlite.Upsert(db, cars)
    if err != nil {
        panic(err)
    }

    bikes := &Topic{Content: "Bikes", Authors: []*Author{john}}
    err = ormlite.Upsert(db, bikes)
    if err != nil {
        panic(err)
    }

    planes := &Topic{Content: "Plains", Authors: []*Author{pete}}
    err = ormlite.Upsert(db, planes)
    if err != nil {
        panic(err)
    }

    var carAuthors []*Author
    err = ormlite.QuerySlice(db, &ormlite.Options{RelatedTo: []ormlite.IModel{&Topic{Id: cars.Id}}}, &carAuthors)
    if err != nil {
        panic(err)
    }

    var planeAuthors []*Author
    err = ormlite.QuerySlice(db, &ormlite.Options{RelatedTo: []ormlite.IModel{&Topic{Id: planes.Id}}}, &planeAuthors)
    if err != nil {
        panic(err)
    }

    fmt.Print("Car authors: ")
    for _, a := range carAuthors {
        fmt.Printf("%s ", a.Name)
    }
    fmt.Print("\n")

    fmt.Print("Plane authors: ")
    for _, a := range planeAuthors {
        fmt.Printf("%s ", a.Name)
    }

将输出:

Car authors: John Pete 
Plane authors: Pete 

比较运算符

默认情况下,包使用=运算符来比较Where结构中引入的值,字符串除外,它们使用LIKE运算符进行比较。但可以使用以下其他运算符列表:

  • Greater 代表 >
  • GreaterOrEqual 代表 >=
  • Less 代表 <
  • LessOrEqual 代表 <=
  • NotEqual 代表 !=
  • BitwiseAND 代表 value&? > 0
  • BitwiseANDStrict 代表 value&? = 0
  • StrictString - 默认情况下字符串比较使用LIKE运算符,StrictString将强制使用=

要使用这些运算符,只需用它们包装值

opts := &ormlite.Options{Where: {"Age": GreaterOrEqual(10)}}

更多示例

参见测试。


更多关于golang轻量级SQLite数据库ORM功能插件库ormlite的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang轻量级SQLite数据库ORM功能插件库ormlite的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


ormlite - Golang轻量级SQLite ORM库使用指南

ormlite是一个轻量级的Golang ORM库,专门为SQLite数据库设计,提供了简单易用的API来操作SQLite数据库。下面我将详细介绍ormlite的使用方法。

安装ormlite

go get github.com/mattn/ormlite

基本使用方法

1. 定义模型结构体

type User struct {
    ID        int    `orm:"primary_key"`
    Name      string `orm:"size:100"`
    Age       int
    CreatedAt time.Time `orm:"auto_now_add"`
    UpdatedAt time.Time `orm:"auto_now"`
}

2. 初始化数据库连接

import (
    "github.com/mattn/ormlite"
    _ "github.com/mattn/go-sqlite3"
)

func main() {
    db, err := ormlite.Open("sqlite3", "test.db")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    
    // 自动迁移表结构
    err = db.AutoMigrate(&User{})
    if err != nil {
        panic(err)
    }
}

3. CRUD操作示例

创建记录

// 创建单个记录
user := User{Name: "Alice", Age: 25}
result := db.Create(&user)
if result.Error != nil {
    panic(result.Error)
}

// 批量创建
users := []User{
    {Name: "Bob", Age: 30},
    {Name: "Charlie", Age: 35},
}
result = db.Create(&users)

查询记录

// 查询单个记录
var user User
result := db.First(&user, 1) // 通过主键查询
result = db.First(&user, "name = ?", "Alice") // 条件查询

// 查询多个记录
var users []User
result = db.Where("age > ?", 20).Find(&users)

// 排序和限制
result = db.Order("age desc").Limit(10).Find(&users)

更新记录

// 更新单个字段
result := db.Model(&User{}).Where("id = ?", 1).Update("name", "Alice Updated")

// 更新多个字段
result = db.Model(&user).Updates(User{Name: "Alice", Age: 26})

// 更新所有匹配记录
result = db.Model(&User{}).Where("age > ?", 30).Update("age", ormlite.Expr("age + ?", 1))

删除记录

// 删除单个记录
result := db.Delete(&User{}, 1)

// 条件删除
result = db.Where("name = ?", "Bob").Delete(&User{})

4. 事务处理

err := db.Transaction(func(tx *ormlite.DB) error {
    if err := tx.Create(&User{Name: "TxUser", Age: 40}).Error; err != nil {
        return err
    }
    
    if err := tx.Model(&User{}).Where("name = ?", "Alice").Update("age", 27).Error; err != nil {
        return err
    }
    
    return nil
})

if err != nil {
    panic(err)
}

5. 高级查询

// 预加载关联(如果有关联关系)
type Post struct {
    ID      int
    Title   string
    Content string
    UserID  int
    User    User
}

var post Post
db.Preload("User").First(&post, 1)

// 原生SQL查询
var users []User
db.Raw("SELECT * FROM users WHERE age > ?", 25).Scan(&users)

// 计数
var count int64
db.Model(&User{}).Where("age > ?", 20).Count(&count)

特性总结

  1. 轻量级: 专门为SQLite优化,不包含复杂ORM的所有功能
  2. 简单API: 类似GORM的API设计,学习曲线平缓
  3. 自动迁移: 支持自动创建和更新表结构
  4. 事务支持: 提供简单的事务处理机制
  5. 链式调用: 支持方法链式调用构建查询

注意事项

  1. ormlite是专门为SQLite设计的,不适用于其他数据库
  2. 对于复杂查询,可能需要直接使用原生SQL
  3. 性能敏感场景下,可以考虑直接使用database/sql接口
  4. 确保在结构体字段中正确定义标签(如primary_key等)

ormlite非常适合中小型项目,特别是那些需要简单ORM功能而不想引入复杂框架的场景。它的轻量级特性和对SQLite的专门优化使其成为这类项目的理想选择。

回到顶部