Skip to content

Latest commit

 

History

History
335 lines (271 loc) · 7.96 KB

File metadata and controls

335 lines (271 loc) · 7.96 KB

快速入门

本文档帮助你快速上手 daog,从环境准备到完成第一个 CRUD 示例。

环境准备

系统要求

  • Go 1.18+ (需要泛型支持)
  • MySQL 5.7+

安装 daog

go get github.com/rolandhe/daog

安装 compilex 代码生成工具

go install github.com/rolandhe/compilex@latest

验证安装:

compilex -h

从 SQL 生成代码

1. 准备建表语句

创建 schema.sql 文件:

CREATE TABLE `user_info` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `name` varchar(64) NOT NULL COMMENT '用户名',
  `email` varchar(128) NOT NULL COMMENT '邮箱',
  `age` int NOT NULL DEFAULT 0 COMMENT '年龄',
  `status` tinyint NOT NULL DEFAULT 1 COMMENT '状态:1-正常 0-禁用',
  `created_at` datetime NOT NULL COMMENT '创建时间',
  `updated_at` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';

2. 执行代码生成

compilex -i="schema.sql" -pkg dal -o ./dal

参数说明:

  • -i: 输入的 SQL 文件路径
  • -pkg: 生成代码的包名
  • -o: 输出目录

3. 生成的文件

执行后会生成两个文件:

UserInfo.go(不可修改)

package dal

import (
    "github.com/rolandhe/daog"
    "github.com/rolandhe/daog/ttypes"
)

// 字段名常量
var UserInfoFields = struct {
    Id        string
    Name      string
    Email     string
    Age       string
    Status    string
    CreatedAt string
    UpdatedAt string
}{
    "id",
    "name",
    "email",
    "age",
    "status",
    "created_at",
    "updated_at",
}

// 表元数据
var UserInfoMeta = &daog.TableMeta[UserInfo]{
    Table:      "user_info",
    Columns:    []string{"id", "name", "email", "age", "status", "created_at", "updated_at"},
    AutoColumn: "id",
    LookupFieldFunc: func(columnName string, ins *UserInfo, point bool) any {
        // 字段映射逻辑...
    },
}

// QuickDao 实例
var UserInfoDao daog.QuickDao[UserInfo] = daog.NewBaseQuickDao(UserInfoMeta)

// 数据结构
type UserInfo struct {
    Id        int64
    Name      string
    Email     string
    Age       int
    Status    int8
    CreatedAt ttypes.NormalDatetime
    UpdatedAt ttypes.NormalDatetime
}

UserInfo-ext.go(可修改)

package dal

func init() {
    // 可以在这里设置分表函数
    // UserInfoMeta.ShardingFunc = func(tableName string, key any) string {
    //     return fmt.Sprintf("%s_%d", tableName, key.(int64)%10)
    // }
}

// 可以在这里添加自定义的数据访问方法

配置数据源

package main

import (
    "log"

    "github.com/rolandhe/daog"
    _ "github.com/go-sql-driver/mysql"
)

var datasource daog.Datasource

func init() {
    conf := &daog.DbConf{
        DbUrl:          "root:password@tcp(localhost:3306)/testdb?parseTime=true",
        Size:           20,     // 最大连接数
        Life:           3600,   // 连接最大生命周期(秒)
        IdleCons:       10,     // 最大空闲连接数
        IdleTime:       600,    // 最大空闲时间(秒)
        LogSQL:         true,   // 开启 SQL 日志
        GetConnTimeout: 10,     // 获取连接超时(秒)
    }

    var err error
    datasource, err = daog.NewDatasource(conf)
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    defer datasource.Shutdown()

    // 使用 datasource 进行数据库操作...
}

第一个 CRUD 示例

完整示例代码

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/rolandhe/daog"
    "github.com/rolandhe/daog/ttypes"
    txrequest "github.com/rolandhe/daog/tx"
    "your/project/dal"
    _ "github.com/go-sql-driver/mysql"
)

var datasource daog.Datasource

func init() {
    conf := &daog.DbConf{
        DbUrl:  "root:password@tcp(localhost:3306)/testdb?parseTime=true",
        LogSQL: true,
    }
    var err error
    datasource, err = daog.NewDatasource(conf)
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    defer datasource.Shutdown()

    // 1. 创建用户
    user, err := createUser("张三", "zhangsan@example.com", 25)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("创建用户成功,ID: %d\n", user.Id)

    // 2. 查询用户
    user, err = getUserById(user.Id)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("查询用户:%+v\n", user)

    // 3. 更新用户
    err = updateUserAge(user.Id, 26)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("更新用户成功")

    // 4. 条件查询
    users, err := queryActiveUsers()
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("查询到 %d 个活跃用户\n", len(users))

    // 5. 删除用户
    err = deleteUser(user.Id)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("删除用户成功")
}

// 创建用户
func createUser(name, email string, age int) (*dal.UserInfo, error) {
    return daog.AutoTransWithResult(func() (*daog.TransContext, error) {
        return daog.NewTransContext(datasource, txrequest.RequestWrite, "create-user")
    }, func(tc *daog.TransContext) (*dal.UserInfo, error) {
        now := ttypes.NormalDatetime(time.Now())
        user := &dal.UserInfo{
            Name:      name,
            Email:     email,
            Age:       age,
            Status:    1,
            CreatedAt: now,
            UpdatedAt: now,
        }
        _, err := dal.UserInfoDao.Insert(tc, user)
        if err != nil {
            return nil, err
        }
        // user.Id 已自动回填
        return user, nil
    })
}

// 根据 ID 查询用户
func getUserById(id int64) (*dal.UserInfo, error) {
    return daog.AutoTransWithResult(func() (*daog.TransContext, error) {
        return daog.NewTransContext(datasource, txrequest.RequestReadonly, "get-user")
    }, func(tc *daog.TransContext) (*dal.UserInfo, error) {
        return dal.UserInfoDao.GetById(tc, id)
    })
}

// 更新用户年龄
func updateUserAge(id int64, newAge int) error {
    return daog.AutoTrans(func() (*daog.TransContext, error) {
        return daog.NewTransContext(datasource, txrequest.RequestWrite, "update-user")
    }, func(tc *daog.TransContext) error {
        modifier := daog.NewModifier().
            Add(dal.UserInfoFields.Age, newAge).
            Add(dal.UserInfoFields.UpdatedAt, ttypes.NormalDatetime(time.Now()))
        _, err := dal.UserInfoDao.UpdateById(tc, modifier, id)
        return err
    })
}

// 查询活跃用户
func queryActiveUsers() ([]*dal.UserInfo, error) {
    return daog.AutoTransWithResult(func() (*daog.TransContext, error) {
        return daog.NewTransContext(datasource, txrequest.RequestReadonly, "query-users")
    }, func(tc *daog.TransContext) ([]*dal.UserInfo, error) {
        matcher := daog.NewMatcher().Eq(dal.UserInfoFields.Status, 1)
        return dal.UserInfoDao.QueryListMatcher(tc, matcher,
            daog.NewDescOrder(dal.UserInfoFields.CreatedAt))
    })
}

// 删除用户
func deleteUser(id int64) error {
    return daog.AutoTrans(func() (*daog.TransContext, error) {
        return daog.NewTransContext(datasource, txrequest.RequestWrite, "delete-user")
    }, func(tc *daog.TransContext) error {
        _, err := dal.UserInfoDao.DeleteById(tc, id)
        return err
    })
}

两种使用方式

1. 函数方式

直接调用 daog 包提供的函数,需要传递 TableMeta:

user, err := daog.GetById(tc, id, dal.UserInfoMeta)
_, err := daog.Insert(tc, user, dal.UserInfoMeta)

2. QuickDao 方式(推荐)

使用生成的 Dao 实例,无需传递 TableMeta:

user, err := dal.UserInfoDao.GetById(tc, id)
_, err := dal.UserInfoDao.Insert(tc, user)

两种方式功能完全相同,QuickDao 代码更简洁。

下一步