1 介绍

1.1 简介

01.ORM框架
    a.框架定位
        a.对象关系映射
            a.核心概念
                xorm是Go语言的简单而强大的ORM库
                将数据库表映射为Go结构体
                提供简洁的链式API操作数据库
            b.技术优势
                轻量级设计
                性能优异
                易于学习和使用
        b.数据库支持
            a.多数据库
                MySQL、PostgreSQL、SQLite
                SQL Server、Oracle、TiDB
                统一的操作接口
            b.驱动实现
                标准database/sql接口
                支持多种数据库��动
                易于扩展新数据库
    b.核心特性
        a.基础功能
            a.CRUD操作
                Insert、Get、Update、Delete
                批量操作支持
                链式调用API
            b.查询构建
                灵活的条件查询
                支持原生SQL
                SQL构建器
        b.高级功能
            a.缓存机制
                内置查询缓存
                支持多种缓存后端
                自动缓存失效
    c.设计理念
        a.简单易用
            a.API设计
                直观的方法命名
                链式调用风格
                丰富的示例文档
            b.学习成本
                快速上手
                文档完善
                社区活跃
    d.版本演进
        a.稳定版本
            a.v1版本
                成熟稳定
                功能完整
                广泛使用
            b.持续维护
                定期更新
                bug修复
                性能优化

1.2 核心特性

01.CRUD操作
    a.Insert插入
        a.基础插入
            // 定义模型
            type User struct {
                Id      int64     `xorm:"pk autoincr"`
                Name    string    `xorm:"varchar(100) notnull"`
                Email   string    `xorm:"varchar(100) unique notnull"`
                Age     int       `xorm:"default 0"`
                Created time.Time `xorm:"created"`
                Updated time.Time `xorm:"updated"`
            }

            // 插入记录
            user := User{Name: "Alice", Email: "[email protected]", Age: 25}
            affected, err := engine.Insert(&user)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("Inserted ID: %d\n", user.Id)

            // 批量插入
            users := []User{
                {Name: "Bob", Email: "[email protected]"},
                {Name: "Charlie", Email: "[email protected]"},
            }
            engine.Insert(&users)
    b.Get查询
        a.基础查询
            // 查询单条记录
            user := User{Id: 1}
            has, err := engine.Get(&user)

            // 条件查询
            user := User{}
            has, err := engine.Where("email = ?", "[email protected]").Get(&user)

            // 查询所有记录
            users := make([]User, 0)
            err := engine.Find(&users)

            // 条件查询
            err := engine.Where("age > ?", 18).Find(&users)
            err := engine.In("name", "Alice", "Bob").Find(&users)

            // 链式查询
            err := engine.Where("age > ?", 18).
                And("email like ?", "%@example.com").
                OrderBy("created desc").
                Limit(10, 0).
                Find(&users)

            // 查询指定字段
            err := engine.Cols("name", "email").Find(&users)

            // 统计数量
            count, err := engine.Where("age > ?", 18).Count(&User{})
    c.Update更新
        a.更新记录
            // 更新单个字段
            user := User{Name: "Alice Updated"}
            engine.Id(1).Update(&user)

            // 更新多个字段
            user := User{Name: "Alice", Age: 26}
            engine.Id(1).AllCols().Update(&user)

            // 使用Map更新
            engine.Table("user").Id(1).Update(map[string]interface{}{
                "name": "Alice",
                "age":  26,
            })

            // 批量更新
            engine.Where("age < ?", 18).Update(&User{Status: "minor"})

            // 更新表达式
            engine.Id(1).Incr("age", 1).Update(&User{})
    d.Delete删除
        a.删除记录
            // 删除单条记录
            user := User{Id: 1}
            engine.Delete(&user)

            // 条件删除
            engine.Where("age < ?", 18).Delete(&User{})

            // 软删除(需要deleted字段)
            type User struct {
                Id      int64
                Name    string
                Deleted time.Time `xorm:"deleted"`
            }

            engine.Delete(&user)  // 软删除,设置deleted

            // 物理删除
            engine.Unscoped().Delete(&user)

            // 查询包含软删除的记录
            engine.Unscoped().Where("age > ?", 18).Find(&users)

02.查询构建
    a.链式API
        a.复杂查询
            // 链式查询示例
            users := make([]User, 0)
            err := engine.Where("age > ?", 18).
                And("email like ?", "%@example.com").
                Or("status = ?", "active").
                OrderBy("created desc").
                Limit(10, 0).
                Find(&users)

            // 子查询
            subQuery := engine.Table("order").
                Select("user_id").
                Where("amount > ?", 1000)

            engine.In("id", subQuery).Find(&users)

            // 分组聚合
            type Result struct {
                Date  time.Time
                Total int
            }
            results := make([]Result, 0)
            engine.Table("order").
                Select("DATE(created) as date, SUM(amount) as total").
                GroupBy("DATE(created)").
                Having("SUM(amount) > ?", 1000).
                Find(&results)

03.缓存机制
    a.查询缓存
        a.缓存配置
            // 内存缓存
            cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
            engine.SetDefaultCacher(cacher)

            // 查询使用缓存
            user := User{}
            engine.Id(1).Get(&user)  // 第一次查询数据库
            engine.Id(1).Get(&user)  // 第二次从缓存读取

            // 清除缓存
            engine.ClearCache(&User{})

04.事务支持
    a.事务处理
        a.事务操作
            // 手动事务
            session := engine.NewSession()
            defer session.Close()

            err := session.Begin()
            if err != nil {
                return err
            }

            _, err = session.Insert(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            _, err = session.Insert(&profile)
            if err != nil {
                session.Rollback()
                return err
            }

            err = session.Commit()

1.3 优缺点

01.主要优点
    a.性能优异
        轻量级设计,内存占用少
        查询性能高
        支持查询缓存
    b.简单易用
        API简洁直观
        学习曲线平缓
        文档完善
    c.功能丰富
        内置缓存机制
        支持事务
        支持多数据库

02.主要缺点
    a.关联处理
        关联关系需要手动处理
        不支持自动预加载
        级联操作需要手动实现
    b.社区规模
        社区相对较小
        第三方插件较少
        更新频率较低
    c.高级特性
        缺少迁移工具
        缺少模型验证
        缺少软删除自动处理

03.适用场景
    a.中小型项目
        快速开发
        CRUD应用
        API服务
    b.性能要求高
        高并发场景
        查询密集型应用
        需要缓存支持

04.不适用场景
    a.复杂关联
        多层级关联
        复杂的关联查询
        需要自动预加载
    b.大型项目
        需要完善的迁移工具
        需要丰富的生态
        需要企业级支持

1.4 使用场景

01.Web应用
    a.后台管理系统
        // 用户管理CRUD
        engine.Insert(&user)
        engine.Find(&users)
        engine.Id(1).Update(&user)
        engine.Delete(&user)

02.API服务
    a.RESTful API
        func GetUsers(c *gin.Context) {
            users := make([]User, 0)
            engine.Find(&users)
            c.JSON(200, users)
        }

03.数据处理
    a.批量导入
        engine.Insert(&users)  // 批量插入

04.高性能场景
    a.缓存应用
        // 启用缓存
        cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
        engine.SetDefaultCacher(cacher)

        // 查询自动使用缓存
        engine.Id(1).Get(&user)

1.5 快速开始

01.安装配置
    a.安装xorm
        a.安装命令
            go get xorm.io/xorm
            go get github.com/go-sql-driver/mysql
        b.导入包
            import (
                "xorm.io/xorm"
                _ "github.com/go-sql-driver/mysql"
            )

02.创建引擎
    a.MySQL连接
        a.基础连接
            engine, err := xorm.NewEngine("mysql",
                "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4")
            if err != nil {
                log.Fatal(err)
            }
            defer engine.Close()
        b.连接测试
            err = engine.Ping()
            if err != nil {
                log.Fatal("数据库连接失败:", err)
            }

03.模型定义
    a.基础模型
        a.结构体定义
            type User struct {
                Id        int64     `xorm:"pk autoincr"`
                Name      string    `xorm:"varchar(100) notnull"`
                Email     string    `xorm:"varchar(100) unique"`
                Age       int       `xorm:"default 0"`
                Created   time.Time `xorm:"created"`
                Updated   time.Time `xorm:"updated"`
            }
        b.表名映射
            func (User) TableName() string {
                return "users"
            }

04.基础操作
    a.CRUD示例
        a.创建表
            err := engine.Sync2(new(User))
        b.插入数据
            user := User{Name: "Alice", Email: "[email protected]", Age: 25}
            affected, err := engine.Insert(&user)
            fmt.Printf("Inserted ID: %d\n", user.Id)
        c.查询数据
            user := User{Id: 1}
            has, err := engine.Get(&user)
            if has {
                fmt.Printf("User: %+v\n", user)
            }
        d.更新数据
            user.Age = 26
            engine.Id(user.Id).Update(&user)
        e.删除数据
            engine.Id(user.Id).Delete(&User{})

05.配置选项
    a.引擎配置
        a.日志配置
            engine.ShowSQL(true)  // 显示SQL
            engine.Logger().SetLevel(core.LOG_DEBUG)
        b.连接池配置
            engine.SetMaxIdleConns(10)
            engine.SetMaxOpenConns(100)
            engine.SetConnMaxLifetime(time.Hour)
        c.时区配置
            engine.TZLocation, _ = time.LoadLocation("Asia/Shanghai")

06.表同步
    a.Sync2方法
        a.自动同步
            // 同步单个表
            err := engine.Sync2(new(User))

            // 同步多个表
            err := engine.Sync2(new(User), new(Order), new(Product))
        b.同步说明
            // Sync2会:
            // 1. 创建不存在的表
            // 2. 添加缺失的字段
            // 3. 创建缺失的索引
            // 不会:删除字段、修改字段类型

1.6 数据库连接

01.连接字符串
    a.DSN配置
        a.MySQL
            dsn := "user:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=true"
            engine, err := xorm.NewEngine("mysql", dsn)
        b.PostgreSQL
            dsn := "postgres://user:password@host:port/dbname?sslmode=disable"
            engine, err := xorm.NewEngine("postgres", dsn)
        c.SQLite
            engine, err := xorm.NewEngine("sqlite3", "./test.db")
        d.SQL Server
            dsn := "server=localhost;user id=sa;password=pwd;database=test"
            engine, err := xorm.NewEngine("mssql", dsn)

02.连接池
    a.连接池配置
        a.参数设置
            engine.SetMaxIdleConns(10)      // 最大空闲连接数
            engine.SetMaxOpenConns(100)     // 最大打开连接数
            engine.SetConnMaxLifetime(time.Hour)  // 连接最大生命周期
        b.连接检查
            err := engine.Ping()
            if err != nil {
                log.Fatal("数据库��接失败")
            }

03.多数据库
    a.多引擎
        a.多个数据库
            userEngine, _ := xorm.NewEngine("mysql", userDSN)
            orderEngine, _ := xorm.NewEngine("mysql", orderDSN)

            // 分别操作不同数据库
            userEngine.Insert(&user)
            orderEngine.Insert(&order)
        b.读写分离
            // 主库
            masterEngine, _ := xorm.NewEngine("mysql", masterDSN)
            // 从库
            slaveEngine, _ := xorm.NewEngine("mysql", slaveDSN)

            // 写操作用主库
            masterEngine.Insert(&user)
            // 读操作用从库
            slaveEngine.Find(&users)

04.连接管理
    a.连接生命周期
        a.创建连接
            engine, err := xorm.NewEngine("mysql", dsn)
            if err != nil {
                log.Fatal(err)
            }
        b.测试连接
            err = engine.Ping()
        c.关闭连接
            defer engine.Close()
        d.连接监控
            stats := engine.DB().Stats()
            fmt.Printf("Open: %d, InUse: %d, Idle: %d\n",
                stats.OpenConnections, stats.InUse, stats.Idle)

05.引擎配置
    a.全局配置
        a.日志配置
            engine.ShowSQL(true)  // 显示执行的SQL
            engine.Logger().SetLevel(core.LOG_DEBUG)  // 设置日志级别
        b.表名映射
            // 设置表名前缀
            tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, "t_")
            engine.SetTableMapper(tbMapper)

            // 设置列名映射
            engine.SetColumnMapper(core.SnakeMapper{})
        c.缓存配置
            cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
            engine.SetDefaultCacher(cacher)

06.错误处理
    a.连接错误
        a.错误检查
            engine, err := xorm.NewEngine("mysql", dsn)
            if err != nil {
                log.Fatal("创建引擎失败:", err)
            }

            err = engine.Ping()
            if err != nil {
                log.Fatal("数据库连接失败:", err)
            }
        b.重连机制
            // 设置连接重试
            for i := 0; i < 3; i++ {
                err = engine.Ping()
                if err == nil {
                    break
                }
                time.Sleep(time.Second * 2)
            }

2 模型定义

2.1 汇总:6个

01.模型声明
    结构体定义、字段类型、标签、约定

02.字段标签
    pk、autoincr、notnull、unique、index

03.主键和索引
    主键定义、复合主键、索引创建、唯一索引

04.表映射
    表名映射、表名前缀、命名规则、自定义表名

05.字段映射
    列名映射、字段忽略、字段转换、命名规则

06.模型钩子
    BeforeInsert、AfterInsert、生命周期、业务逻辑

2.2 模型声明

01.基础模型
    a.结构体定义
        a.基本结构
            type User struct {
                Id      int64
                Name    string
                Email   string
                Created time.Time `xorm:"created"`
                Updated time.Time `xorm:"updated"`
            }
        b.完整示例
            type User struct {
                Id        int64     `xorm:"pk autoincr"`
                Name      string    `xorm:"varchar(100) notnull"`
                Email     string    `xorm:"varchar(100) unique"`
                Age       int       `xorm:"default 0"`
                Status    int       `xorm:"default 1"`
                Created   time.Time `xorm:"created"`
                Updated   time.Time `xorm:"updated"`
                DeletedAt time.Time `xorm:"deleted"`
            }

02.字段类型
    a.常用类型
        a.基础类型
            type Product struct {
                Id       int64
                Name     string
                Price    float64
                Stock    int
                IsActive bool
                Data     []byte
                Created  time.Time
            }
        b.指针类型
            type User struct {
                Id    int64
                Name  string
                Age   *int     // 可为NULL
                Email *string  // 可为NULL
            }

03.默认值
    a.默认值设置
        a.标签设置
            type User struct {
                Id     int64
                Name   string `xorm:"default 'guest'"`
                Age    int    `xorm:"default 18"`
                Status int    `xorm:"default 1"`
            }
        b.代码设置
            user := User{
                Name:   "Alice",
                Age:    25,
                Status: 1,
            }

04.字段约束
    a.约束定义
        a.NOT NULL
            type User struct {
                Name  string `xorm:"notnull"`
                Email string `xorm:"notnull"`
            }
        b.UNIQUE
            type User struct {
                Email string `xorm:"unique"`
                Phone string `xorm:"unique"`
            }
        c.CHECK约束
            // xorm不直接支持CHECK约束
            // 需要在数据库层面或应用层实现

2.3 字段标签

01.主键标签
    a.pk标签
        a.单主键
            type User struct {
                Id int64 `xorm:"pk autoincr"`
            }
        b.自定义主键
            type User struct {
                UUID string `xorm:"pk varchar(36)"`
            }

02.类型标签
    a.数据类型
        a.字符串类型
            type Article struct {
                Title   string `xorm:"varchar(200)"`
                Content string `xorm:"text"`
                Summary string `xorm:"varchar(500)"`
            }
        b.数值类型
            type Product struct {
                Price  float64 `xorm:"decimal(10,2)"`
                Stock  int     `xorm:"int"`
                Views  int64   `xorm:"bigint"`
            }

03.约束标签
    a.常用约束
        a.NOT NULL
            type User struct {
                Name  string `xorm:"notnull"`
                Email string `xorm:"notnull"`
            }
        b.UNIQUE
            type User struct {
                Email string `xorm:"unique"`
            }
        c.DEFAULT
            type User struct {
                Status int `xorm:"default 1"`
            }

04.其他标签
    a.时间标签
        a.自动时间
            type User struct {
                Created time.Time `xorm:"created"`  // 创建时自动设置
                Updated time.Time `xorm:"updated"`  // 更新时自动设置
                Deleted time.Time `xorm:"deleted"`  // 软删除标记
            }
        b.版本标签
            type User struct {
                Version int `xorm:"version"`  // 乐观锁
            }
    b.索引标签
        a.普通索引
            type User struct {
                Name string `xorm:"index"`
            }
        b.唯一索引
            type User struct {
                Email string `xorm:"unique"`
            }
    c.忽略标签
        a.忽略字段
            type User struct {
                Id       int64
                Name     string
                Password string `xorm:"-"`  // 不映射到数���库
            }

2.4 主键和索引

01.主键定义
    a.主键设置
        a.自增主键
            type User struct {
                Id int64 `xorm:"pk autoincr"`
            }
        b.UUID主键
            type User struct {
                UUID string `xorm:"pk varchar(36)"`
            }
        c.自定义主键
            type User struct {
                UserId int64 `xorm:"'user_id' pk autoincr"`
            }

02.复合主键
    a.联合主键
        a.多字段主键
            type UserRole struct {
                UserId int64 `xorm:"pk"`
                RoleId int64 `xorm:"pk"`
            }
        b.使用示例
            userRole := UserRole{UserId: 1, RoleId: 2}
            engine.Insert(&userRole)

            // 查询
            ur := UserRole{UserId: 1, RoleId: 2}
            has, _ := engine.Get(&ur)

03.索引创建
    a.索引定义
        a.单列索引
            type User struct {
                Name  string `xorm:"index"`
                Email string `xorm:"unique"`
            }
        b.命名索引
            type User struct {
                Name string `xorm:"index(idx_name)"`
                Age  int    `xorm:"index(idx_age)"`
            }
        c.复合索引
            type User struct {
                Name  string `xorm:"index(idx_name_email)"`
                Email string `xorm:"index(idx_name_email)"`
            }

04.索引选项
    a.索引类型
        a.普通索引
            type User struct {
                Name string `xorm:"index"`
            }
        b.唯一索引
            type User struct {
                Email string `xorm:"unique"`
            }
        c.全文索引
            // xorm不直接支持全文索引
            // 需要使用原生SQL创建
            engine.Exec("CREATE FULLTEXT INDEX idx_content ON articles(content)")

2.5 表映射

01.表名映射
    a.默认规则
        a.结构体到表名
            // 默认使用SnakeMapper
            type UserInfo struct {}  // 映射到表 user_info
            type User struct {}      // 映射到表 user
        b.自定义表名
            func (User) TableName() string {
                return "users"
            }

02.表名前缀
    a.全局前缀
        a.设置前缀
            tbMapper := core.NewPrefixMapper(core.SnakeMapper{}, "t_")
            engine.SetTableMapper(tbMapper)

            // User结构体映射到 t_user 表
            type User struct {
                Id   int64
                Name string
            }
        b.后缀设置
            tbMapper := core.NewSuffixMapper(core.SnakeMapper{}, "_tab")
            engine.SetTableMapper(tbMapper)

03.命名规则
    a.映射器类型
        a.SnakeMapper
            // 驼峰转下划线
            engine.SetTableMapper(core.SnakeMapper{})
            // UserInfo -> user_info
        b.SameMapper
            // 保持原样
            engine.SetTableMapper(core.SameMapper{})
            // UserInfo -> UserInfo
        c.GonicMapper
            // 常见缩写特殊处理
            engine.SetTableMapper(core.GonicMapper{})
            // UserID -> user_id (而不是 user_i_d)

04.动态表名
    a.运行时指定
        a.Table方法
            // 指定表名查询
            users := make([]User, 0)
            engine.Table("user_2024").Find(&users)

            // 指定表名插入
            engine.Table("user_2024").Insert(&user)
        b.分表场景
            // 按月分表
            tableName := fmt.Sprintf("user_%s", time.Now().Format("200601"))
            engine.Table(tableName).Insert(&user)

            // 按用户ID分表
            tableIndex := userId % 10
            tableName := fmt.Sprintf("user_%d", tableIndex)
            engine.Table(tableName).Where("id = ?", userId).Get(&user)

05.表别名
    a.Alias方法
        a.使用别名
            // 查询时使用别名
            engine.Alias("u").
                Join("INNER", "order o", "u.id = o.user_id").
                Where("u.age > ?", 18).
                Find(&users)

06.表注释
    a.Comment标签
        a.表注释
            type User struct {
                Id   int64  `xorm:"pk autoincr"`
                Name string `xorm:"varchar(100)"`
            } // xorm:comment('用户表')
        b.字段注释
            type User struct {
                Id   int64  `xorm:"pk autoincr comment('用户ID')"`
                Name string `xorm:"varchar(100) comment('用户名')"`
            }

2.6 字段映射

01.列名映射
    a.默认映射
        a.驼峰转换
            // 默认使用SnakeMapper
            engine.SetColumnMapper(core.SnakeMapper{})

            type User struct {
                UserId   int64   // 映射到 user_id
                UserName string  // 映射到 user_name
            }
        b.自定义列名
            type User struct {
                Id   int64  `xorm:"'user_id' pk"`
                Name string `xorm:"'user_name'"`
            }

02.字段忽略
    a.忽略字段
        a.临时字段
            type User struct {
                Id       int64
                Name     string
                Password string `xorm:"-"`  // 不映射到数据库
                Token    string `xorm:"-"`
            }
        b.使用场景
            // 密码字段不查询
            user := User{}
            engine.Omit("password").Get(&user)

03.字段转换
    a.类型转换
        a.JSON字段
            type User struct {
                Id      int64
                Name    string
                Profile string `xorm:"text"`  // 存储JSON字符串
            }

            // 使用时手动转换
            profileJSON, _ := json.Marshal(profile)
            user.Profile = string(profileJSON)
        b.时间格式
            type User struct {
                Created time.Time `xorm:"created"`
                Updated time.Time `xorm:"updated"`
            }

04.字段选择
    a.Cols方法
        a.指定字段
            // 只查询指定字段
            engine.Cols("id", "name").Get(&user)

            // 只更新指定字段
            engine.Id(1).Cols("name", "age").Update(&user)
        b.AllCols方法
            // 更新所有字段(包括零值)
            engine.Id(1).AllCols().Update(&user)
        c.MustCols方法
            // 必须更新的字段
            engine.Id(1).MustCols("age").Update(&user)
        d.Omit方法
            // 排除指定字段
            engine.Omit("password").Get(&user)
            engine.Id(1).Omit("created").Update(&user)

05.字段扩展
    a.Extends标签
        a.字段扩展
            type User struct {
                Id   int64
                Name string
                Age  int `xorm:"extends"`  // 扩展字段
            }

06.字段验证
    a.应用层验证
        a.验证规则
            func ValidateUser(user *User) error {
                if user.Name == "" {
                    return errors.New("用户名不能为空")
                }
                if user.Age < 0 || user.Age > 150 {
                    return errors.New("年龄不合法")
                }
                return nil
            }

            // 插入前验证
            if err := ValidateUser(&user); err != nil {
                return err
            }
            engine.Insert(&user)

2.7 模型钩子

01.插入钩子
    a.BeforeInsert
        a.插入前处理
            func (u *User) BeforeInsert() {
                u.Created = time.Now()
                u.Status = 1
            }

            // 使用
            user := User{Name: "Alice"}
            engine.Insert(&user)  // 自动调用BeforeInsert
        b.AfterInsert
            func (u *User) AfterInsert() {
                log.Printf("用户 %s 已创建, ID: %d", u.Name, u.Id)
            }

02.更新钩子
    a.BeforeUpdate
        a.更新前处理
            func (u *User) BeforeUpdate() {
                u.Updated = time.Now()
            }

            // 使用
            user.Name = "Bob"
            engine.Id(user.Id).Update(&user)
        b.AfterUpdate
            func (u *User) AfterUpdate() {
                log.Printf("用户 %d 已更新", u.Id)
            }

03.删除钩子
    a.BeforeDelete
        a.删除前处理
            func (u *User) BeforeDelete() {
                log.Printf("准备删除用户: %d", u.Id)
            }

            // 使用
            engine.Id(1).Delete(&User{})
        b.AfterDelete
            func (u *User) AfterDelete() {
                log.Printf("用户 %d 已删除", u.Id)
            }

04.查询钩子
    a.AfterLoad
        a.查询后处理
            func (u *User) AfterLoad() {
                // 查询后的数据处理
                u.Name = strings.ToUpper(u.Name)
            }

            // 使用
            user := User{}
            engine.Id(1).Get(&user)  // 自动调用AfterLoad

05.钩子应用
    a.完整示例
        a.用户模型
            type User struct {
                Id      int64
                Name    string
                Email   string
                Created time.Time
                Updated time.Time
            }

            func (u *User) BeforeInsert() {
                u.Created = time.Now()
                u.Updated = time.Now()
            }

            func (u *User) BeforeUpdate() {
                u.Updated = time.Now()
            }

            func (u *User) AfterInsert() {
                log.Printf("新用户注册: %s", u.Email)
            }

06.钩子注意事项
    a.执行顺序
        a.插入顺序
            // 1. BeforeInsert
            // 2. 执行INSERT
            // 3. AfterInsert
        b.更新顺序
            // 1. BeforeUpdate
            // 2. 执行UPDATE
            // 3. AfterUpdate
    b.错误处理
        a.钩子中的错误
            // 钩子方法不返回error
            // 需要在钩子内部处理错误
            func (u *User) BeforeInsert() {
                if u.Name == "" {
                    // 无法返回错误,只能记录日志
                    log.Error("用户名为空")
                }
            }

3 CRUD操作

3.1 创建记录

01.Insert
    a.单条插入
        a.基础插入
            user := User{Name: "Alice", Email: "[email protected]", Age: 25}
            affected, err := engine.Insert(&user)
            if err != nil {
                log.Fatal(err)
            }
            fmt.Printf("Inserted ID: %d, Affected: %d\n", user.Id, affected)
        b.返回值
            // affected: 影响的行数
            // user.Id: 自动填充的主键ID

02.批量插入
    a.批量创建
        a.切片插入
            users := []User{
                {Name: "Alice", Email: "[email protected]"},
                {Name: "Bob", Email: "[email protected]"},
                {Name: "Charlie", Email: "[email protected]"},
            }
            affected, err := engine.Insert(&users)
            fmt.Printf("Inserted %d records\n", affected)
        b.指针切片
            users := []*User{
                {Name: "Alice", Email: "[email protected]"},
                {Name: "Bob", Email: "[email protected]"},
            }
            engine.Insert(&users)

03.选择字段
    a.指定字段
        a.Cols方法
            // 只插入指定字段
            user := User{Name: "Alice", Email: "[email protected]", Age: 25}
            engine.Cols("name", "email").Insert(&user)
        b.Omit方法
            // 排除指定字段
            engine.Omit("age").Insert(&user)
        c.AllCols方法
            // 插入所有字段(包括零值)
            engine.AllCols().Insert(&user)

04.冲突处理
    a.InsertOne
        a.插入单条
            // 确保只插入一条记录
            affected, err := engine.InsertOne(&user)
            if affected != 1 {
                log.Fatal("插入失败")
            }

3.2 查询记录

01.Get
    a.单条查询
        a.主键查询
            user := User{Id: 1}
            has, err := engine.Get(&user)
            if has {
                fmt.Printf("User: %+v\n", user)
            }
        b.条件查询
            user := User{}
            has, err := engine.Where("email = ?", "[email protected]").Get(&user)
        c.多条件
            user := User{}
            has, err := engine.Where("age > ?", 18).
                And("status = ?", 1).
                Get(&user)

02.Find
    a.多条查询
        a.查询所有
            users := make([]User, 0)
            err := engine.Find(&users)
        b.条件查询
            err := engine.Where("age > ?", 18).Find(&users)
        c.IN查询
            err := engine.In("id", 1, 2, 3).Find(&users)
            err := engine.In("name", "Alice", "Bob").Find(&users)

03.Iterate
    a.迭代查询
        a.逐行处理
            err := engine.Where("age > ?", 18).Iterate(&User{}, func(i int, bean interface{}) error {
                user := bean.(*User)
                fmt.Printf("User %d: %s\n", i, user.Name)
                return nil
            })

04.Count
    a.计数
        a.统计数量
            count, err := engine.Count(&User{})
            fmt.Printf("Total users: %d\n", count)
        b.条件计数
            count, err := engine.Where("age > ?", 18).Count(&User{})
        c.Distinct计数
            count, err := engine.Distinct("name").Count(&User{})

3.3 更新记录

01.Update
    a.更新记录
        a.主���更新
            user := User{Id: 1, Name: "Alice Updated", Age: 26}
            affected, err := engine.Id(1).Update(&user)
            fmt.Printf("Updated %d records\n", affected)
        b.条件更新
            user := User{Status: 1}
            engine.Where("age < ?", 18).Update(&user)

02.字段选择
    a.Cols更新
        a.指定字段
            // 只更新指定字段
            user := User{Name: "Alice", Age: 26}
            engine.Id(1).Cols("name", "age").Update(&user)
        b.AllCols更新
            // 更新所有字段(包括零值)
            user := User{Name: "Alice", Age: 0}
            engine.Id(1).AllCols().Update(&user)
        c.MustCols更新
            // 必须更新的字段
            user := User{Age: 0}
            engine.Id(1).MustCols("age").Update(&user)

03.增减操作
    a.Incr/Decr
        a.字段增加
            // 年龄+1
            engine.Id(1).Incr("age", 1).Update(&User{})
        b.字段减少
            // 库存-1
            engine.Id(1).Decr("stock", 1).Update(&Product{})
        c.组合操作
            // 年龄+1,积分+10
            engine.Id(1).Incr("age", 1).Incr("points", 10).Update(&User{})

04.批量更新
    a.条件更新
        a.批量修改
            // 更新所有符合条件的记录
            user := User{Status: 1}
            affected, err := engine.Where("age < ?", 18).Update(&user)
        b.Map更新
            // 使用Map更新
            affected, err := engine.Table("user").
                Where("age < ?", 18).
                Update(map[string]interface{}{
                    "status": 1,
                    "level":  "junior",
                })

3.4 删除记录

01.Delete
    a.删除记录
        a.主键删除
            user := User{Id: 1}
            affected, err := engine.Delete(&user)
            fmt.Printf("Deleted %d records\n", affected)
        b.条件删除
            affected, err := engine.Where("age < ?", 18).Delete(&User{})
        c.ID删除
            affected, err := engine.Id(1).Delete(&User{})

02.批量删除
    a.条件删除
        a.批量删除
            // 删除所有符合条件的记录
            affected, err := engine.Where("status = ?", 0).Delete(&User{})
        b.IN删除
            // 删除指定ID的记录
            affected, err := engine.In("id", 1, 2, 3).Delete(&User{})

03.软删除
    a.deleted标签
        a.软删除字段
            type User struct {
                Id      int64
                Name    string
                Deleted time.Time `xorm:"deleted"`
            }

            // 删除时自动设置deleted字段
            engine.Id(1).Delete(&User{})
        b.查询过滤
            // 默认查询会过滤已删除记录
            users := make([]User, 0)
            engine.Find(&users)  // 不包含已删除记录

04.物���删除
    a.Unscoped
        a.永久删除
            // 物理删除(忽略软删除)
            engine.Id(1).Unscoped().Delete(&User{})
        b.查询已删除
            // 查询包含已删除的记录
            users := make([]User, 0)
            engine.Unscoped().Find(&users)

3.5 批量操作

01.批量插入
    a.Insert批量
        a.切片插入
            users := []User{
                {Name: "Alice", Email: "[email protected]"},
                {Name: "Bob", Email: "[email protected]"},
                {Name: "Charlie", Email: "[email protected]"},
            }
            affected, err := engine.Insert(&users)
            fmt.Printf("Inserted %d records\n", affected)

02.批量更新
    a.条件更新
        a.批量修改
            // 更新所有符合条件的记录
            user := User{Status: 1, Level: "vip"}
            affected, err := engine.Where("points > ?", 1000).Update(&user)
        b.Map批量更新
            affected, err := engine.Table("user").
                Where("age < ?", 18).
                Update(map[string]interface{}{
                    "status": 0,
                    "level":  "junior",
                })

03.批量删除
    a.条件删除
        a.批量删除
            // 删除6个月前的记录
            affected, err := engine.Where("created < ?",
                time.Now().AddDate(0, -6, 0)).Delete(&User{})
        b.IN删除
            affected, err := engine.In("id", 1, 2, 3, 4, 5).Delete(&User{})

04.事务批量
    a.事务处理
        a.批量操作
            session := engine.NewSession()
            defer session.Close()

            err := session.Begin()
            if err != nil {
                return err
            }

            for _, user := range users {
                _, err = session.Insert(&user)
                if err != nil {
                    session.Rollback()
                    return err
                }
            }

            err = session.Commit()
            if err != nil {
                return err
            }

05.性能优化
    a.批量优化
        a.分批处理
            // 分批插入,避免一次性插入过多数据
            batchSize := 1000
            for i := 0; i < len(users); i += batchSize {
                end := i + batchSize
                if end > len(users) {
                    end = len(users)
                }
                batch := users[i:end]
                engine.Insert(&batch)
            }

06.Iterate批量
    a.迭代处理
        a.逐行处理
            // 分批查询并处理
            err := engine.Where("status = ?", 0).
                Iterate(&User{}, func(i int, bean interface{}) error {
                    user := bean.(*User)
                    // 处理每条记录
                    user.Status = 1
                    engine.Id(user.Id).Update(user)
                    return nil
                })

3.6 原生SQL

01.Query
    a.原生查询
        a.SQL查询
            results, err := engine.Query("SELECT * FROM user WHERE age > ?", 18)
            for _, row := range results {
                fmt.Printf("Name: %s\n", row["name"])
            }
        b.QueryString
            results, err := engine.QueryString("SELECT name, email FROM user WHERE age > ?", 18)
            for _, row := range results {
                fmt.Printf("Name: %s, Email: %s\n", row["name"], row["email"])
            }
        c.QueryInterface
            results, err := engine.QueryInterface("SELECT * FROM user WHERE age > ?", 18)

02.Exec
    a.执行SQL
        a.更新SQL
            result, err := engine.Exec("UPDATE user SET status = ? WHERE age > ?", 1, 18)
            affected, _ := result.RowsAffected()
            fmt.Printf("Updated %d records\n", affected)
        b.删除SQL
            result, err := engine.Exec("DELETE FROM user WHERE created < ?",
                time.Now().AddDate(-1, 0, 0))
        c.DDL操作
            _, err := engine.Exec("CREATE INDEX idx_email ON user(email)")

03.SQL构建
    a.SQL方法
        a.原生SQL查询
            users := make([]User, 0)
            err := engine.SQL("SELECT * FROM user WHERE age > ?", 18).Find(&users)
        b.复杂查询
            type Result struct {
                Name  string
                Count int
            }
            results := make([]Result, 0)
            err := engine.SQL(`
                SELECT u.name, COUNT(o.id) as count
                FROM user u
                LEFT JOIN order o ON u.id = o.user_id
                GROUP BY u.id
                HAVING count > 5
            `).Find(&results)

04.使用场景
    a.复杂查询
        a.多表关联
            sql := `
                SELECT u.*, p.bio
                FROM user u
                LEFT JOIN profile p ON u.id = p.user_id
                WHERE u.age > ?
                ORDER BY u.created DESC
                LIMIT 10
            `
            users := make([]User, 0)
            engine.SQL(sql, 18).Find(&users)
        b.聚合统计
            sql := `
                SELECT
                    DATE(created) as date,
                    COUNT(*) as count,
                    SUM(amount) as total
                FROM order
                WHERE created >= ?
                GROUP BY DATE(created)
            `
            results := make([]Result, 0)
            engine.SQL(sql, time.Now().AddDate(0, -1, 0)).Find(&results)

05.参数绑定
    a.位置参数
        a.问号占位符
            users := make([]User, 0)
            engine.SQL("SELECT * FROM user WHERE age > ? AND status = ?", 18, 1).Find(&users)

06.注意事项
    a.SQL注入
        a.防止注入
            // ❌ 错误:直接拼接SQL
            sql := fmt.Sprintf("SELECT * FROM user WHERE name = '%s'", name)

            // ✅ 正确:使用参数绑定
            engine.SQL("SELECT * FROM user WHERE name = ?", name).Find(&users)
        b.安全建议
            // 1. 始终使用参数绑定
            // 2. 不要直接拼接用户输入
            // 3. 验证和过滤用户输入

4 查询进阶

4.1 条件查询

01.Where条件
    a.基础条件
        a.等值查询
            users := make([]User, 0)
            engine.Where("name = ?", "Alice").Find(&users)
            engine.Where("age = ?", 25).Find(&users)
        b.比较查询
            engine.Where("age > ?", 18).Find(&users)
            engine.Where("age >= ?", 18).Find(&users)
            engine.Where("age < ?", 60).Find(&users)
            engine.Where("created > ?", time.Now().AddDate(0, -1, 0)).Find(&users)
        c.模糊查询
            engine.Where("name LIKE ?", "%Alice%").Find(&users)
            engine.Where("email LIKE ?", "%@example.com").Find(&users)

02.多条件
    a.And条件
        a.链式And
            engine.Where("age > ?", 18).
                And("status = ?", 1).
                And("level > ?", 5).
                Find(&users)
        b.多个Where
            // 多个Where等同于And
            engine.Where("age > ?", 18).
                Where("status = ?", 1).
                Find(&users)

03.Or条件
    a.Or查询
        a.Or条件
            engine.Where("age < ?", 18).
                Or("age > ?", 60).
                Find(&users)
        b.复杂Or
            engine.Where("status = ?", 1).
                Or("level = ?", "vip").
                Or("points > ?", 1000).
                Find(&users)

04.In条件
    a.In查询
        a.基础In
            engine.In("id", 1, 2, 3, 4, 5).Find(&users)
            engine.In("name", "Alice", "Bob", "Charlie").Find(&users)
        b.切片In
            ids := []int64{1, 2, 3, 4, 5}
            engine.In("id", ids).Find(&users)
        c.NotIn
            engine.NotIn("status", 0, -1).Find(&users)

05.Between条件
    a.范围查询
        a.数值范围
            // age BETWEEN 18 AND 60
            engine.Where("age >= ? AND age <= ?", 18, 60).Find(&users)
        b.时间范围
            startTime := time.Now().AddDate(0, -1, 0)
            endTime := time.Now()
            engine.Where("created >= ? AND created <= ?", startTime, endTime).Find(&users)

06.Null条件
    a.Null查询
        a.IsNull
            engine.Where("deleted_at IS NULL").Find(&users)
        b.IsNotNull
            engine.Where("email IS NOT NULL").Find(&users)

4.2 排序分页

01.OrderBy排序
    a.单字段排序
        a.升序
            users := make([]User, 0)
            engine.OrderBy("age").Find(&users)
            engine.Asc("age").Find(&users)
        b.降序
            engine.OrderBy("age DESC").Find(&users)
            engine.Desc("age").Find(&users)
        c.多字段排序
            engine.OrderBy("age DESC, name ASC").Find(&users)
            engine.Desc("age").Asc("name").Find(&users)

02.Limit分页
    a.限制数量
        a.Limit方法
            // 查询前10条
            engine.Limit(10).Find(&users)

            // 查询第11-20条
            engine.Limit(10, 10).Find(&users)
        b.分页查询
            page := 2
            pageSize := 10
            engine.Limit(pageSize, (page-1)*pageSize).Find(&users)

03.分页封装
    a.分页函数
        a.通用分页
            type Pagination struct {
                Page     int
                PageSize int
                Total    int64
                Data     interface{}
            }

            func Paginate(engine *xorm.Engine, page, pageSize int, bean interface{}) (*Pagination, error) {
                total, err := engine.Count(bean)
                if err != nil {
                    return nil, err
                }

                err = engine.Limit(pageSize, (page-1)*pageSize).Find(bean)
                if err != nil {
                    return nil, err
                }

                return &Pagination{
                    Page:     page,
                    PageSize: pageSize,
                    Total:    total,
                    Data:     bean,
                }, nil
            }

            // 使用
            users := make([]User, 0)
            pagination, err := Paginate(engine, 2, 10, &users)

04.游标分页
    a.基于ID分页
        a.游标实现
            var lastId int64 = 0
            pageSize := 10

            // 第一页
            users := make([]User, 0)
            engine.Where("id > ?", lastId).
                Asc("id").
                Limit(pageSize).
                Find(&users)

            // 下一页
            if len(users) > 0 {
                lastId = users[len(users)-1].Id
                engine.Where("id > ?", lastId).
                    Asc("id").
                    Limit(pageSize).
                    Find(&users)
            }

05.Distinct去重
    a.去重查询
        a.单字段去重
            users := make([]User, 0)
            engine.Distinct("name").Find(&users)
        b.多字段去重
            engine.Distinct("name", "email").Find(&users)

06.GroupBy分组
    a.分组查询
        a.基础分组
            type Result struct {
                Name  string
                Count int
            }
            results := make([]Result, 0)
            engine.Table("user").
                Select("name, COUNT(*) as count").
                GroupBy("name").
                Find(&results)
        b.Having条件
            engine.Table("user").
                Select("name, COUNT(*) as count").
                GroupBy("name").
                Having("COUNT(*) > ?", 1).
                Find(&results)

4.3 联表查询

01.Join查询
    a.Inner Join
        a.内连接
            type UserOrder struct {
                User  `xorm:"extends"`
                Order `xorm:"extends"`
            }

            results := make([]UserOrder, 0)
            engine.Table("user").
                Join("INNER", "order", "user.id = order.user_id").
                Find(&results)
        b.别名使用
            engine.Table("user").Alias("u").
                Join("INNER", "order o", "u.id = o.user_id").
                Where("u.age > ?", 18).
                Find(&results)

02.Left Join
    a.左连接
        a.基础左连接
            engine.Table("user").
                Join("LEFT", "order", "user.id = order.user_id").
                Find(&results)
        b.多表左连接
            engine.Table("user").Alias("u").
                Join("LEFT", "order o", "u.id = o.user_id").
                Join("LEFT", "product p", "o.product_id = p.id").
                Find(&results)

03.Right Join
    a.右连接
        a.基础右连接
            engine.Table("user").
                Join("RIGHT", "order", "user.id = order.user_id").
                Find(&results)

04.关联查询
    a.一对一查询
        a.用户和资料
            type UserProfile struct {
                User    `xorm:"extends"`
                Profile `xorm:"extends"`
            }

            results := make([]UserProfile, 0)
            engine.Table("user").
                Join("LEFT", "profile", "user.id = profile.user_id").
                Find(&results)
        b.字段选择
            engine.Table("user").Alias("u").
                Join("LEFT", "profile p", "u.id = p.user_id").
                Cols("u.id", "u.name", "p.bio").
                Find(&results)

05.复杂关联
    a.多表关联
        a.三表关联
            type UserOrderProduct struct {
                UserId      int64
                UserName    string
                OrderId     int64
                OrderAmount float64
                ProductName string
            }

            results := make([]UserOrderProduct, 0)
            engine.Table("user").Alias("u").
                Select("u.id as user_id, u.name as user_name, o.id as order_id, o.amount as order_amount, p.name as product_name").
                Join("LEFT", "order o", "u.id = o.user_id").
                Join("LEFT", "product p", "o.product_id = p.id").
                Find(&results)

06.子查询Join
    a.子查询关联
        a.使用子查询
            // 查询有订单的用户
            sql := `
                SELECT u.*
                FROM user u
                INNER JOIN (
                    SELECT DISTINCT user_id
                    FROM order
                    WHERE amount > 1000
                ) o ON u.id = o.user_id
            `
            users := make([]User, 0)
            engine.SQL(sql).Find(&users)

4.4 子查询

01.Where子查询
    a.子查询条件
        a.IN子查询
            // 查询有订单的用户
            users := make([]User, 0)
            engine.In("id",
                engine.Table("order").Select("user_id").Where("amount > ?", 1000),
            ).Find(&users)
        b.比较子查询
            // 查询年龄大于平均年龄的用户
            engine.Where("age > (?)",
                engine.Table("user").Select("AVG(age)"),
            ).Find(&users)

02.From子查询
    a.派生表
        a.子查询作为表
            type Result struct {
                UserId int64
                Total  float64
            }
            results := make([]Result, 0)

            subQuery := engine.Table("order").
                Select("user_id, SUM(amount) as total").
                GroupBy("user_id")

            engine.Table("(?) as t", subQuery).
                Where("total > ?", 1000).
                Find(&results)

03.Exists子查询
    a.Exists查询
        a.存在性查询
            // 查询有订单的用户
            users := make([]User, 0)
            engine.Where("EXISTS (?)",
                engine.Table("order").
                    Select("1").
                    Where("order.user_id = user.id"),
            ).Find(&users)

04.Update子查询
    a.子查询更新
        a.基于子查询更新
            // 将有大额订单的用户设为VIP
            engine.Table("user").
                Where("id IN (?)",
                    engine.Table("order").
                        Select("user_id").
                        Where("amount > ?", 10000),
                ).
                Update(map[string]interface{}{"level": "vip"})

05.性能考虑
    a.优化建议
        a.Join替代
            // ❌ 性能较差:子查询
            engine.In("id",
                engine.Table("order").Select("user_id"),
            ).Find(&users)

            // ✅ 性能更好:JOIN
            engine.Table("user").
                Join("INNER", "order", "user.id = order.user_id").
                Distinct("user.id").
                Find(&users)

06.复���子查询
    a.嵌套子查询
        a.多层嵌套
            // 查询购买了热门商品的用户
            users := make([]User, 0)
            engine.In("id",
                engine.Table("order").
                    Select("user_id").
                    Where("product_id IN (?)",
                        engine.Table("product").
                            Select("id").
                            Where("sales > ?", 1000),
                    ),
            ).Find(&users)

4.5 聚合函数

01.Count计数
    a.计数查询
        a.总数统计
            count, err := engine.Count(&User{})
            fmt.Printf("Total users: %d\n", count)
        b.条件计数
            count, err := engine.Where("age > ?", 18).Count(&User{})
        c.Distinct计数
            count, err := engine.Distinct("name").Count(&User{})

02.Sum求和
    a.求和查询
        a.单字段求和
            type Result struct {
                Total float64
            }
            result := Result{}
            _, err := engine.Table("order").
                Select("SUM(amount) as total").
                Get(&result)
            fmt.Printf("Total amount: %.2f\n", result.Total)
        b.条件求和
            engine.Table("order").
                Select("SUM(amount) as total").
                Where("status = ?", "paid").
                Get(&result)

03.Avg平均值
    a.平均值查询
        a.求平均
            type Result struct {
                Avg float64
            }
            result := Result{}
            engine.Table("user").
                Select("AVG(age) as avg").
                Get(&result)
            fmt.Printf("Average age: %.2f\n", result.Avg)

04.Max/Min
    a.最大最小值
        a.最大值
            type Result struct {
                Max float64
            }
            result := Result{}
            engine.Table("order").
                Select("MAX(amount) as max").
                Get(&result)
        b.最小值
            engine.Table("order").
                Select("MIN(amount) as max").
                Get(&result)

05.GroupBy聚合
    a.分组聚合
        a.基础分组
            type Result struct {
                Name  string
                Count int
                Total float64
            }
            results := make([]Result, 0)
            engine.Table("order").
                Select("user_id, COUNT(*) as count, SUM(amount) as total").
                GroupBy("user_id").
                Find(&results)
        b.Having过滤
            engine.Table("order").
                Select("user_id, COUNT(*) as count, SUM(amount) as total").
                GroupBy("user_id").
                Having("SUM(amount) > ?", 1000).
                Find(&results)

06.多字段聚合
    a.复合聚合
        a.多个聚合函数
            type Result struct {
                Date  string
                Count int
                Total float64
                Avg   float64
                Max   float64
                Min   float64
            }
            results := make([]Result, 0)
            engine.Table("order").
                Select(`
                    DATE(created) as date,
                    COUNT(*) as count,
                    SUM(amount) as total,
                    AVG(amount) as avg,
                    MAX(amount) as max,
                    MIN(amount) as min
                `).
                GroupBy("DATE(created)").
                Find(&results)

4.6 查询优化

01.索引使用
    a.索引优化
        a.查询条件索引
            // 确保查询条件字段有索引
            type User struct {
                Id    int64  `xorm:"pk autoincr"`
                Email string `xorm:"unique"`  // 索引
                Name  string `xorm:"index"`   // 索引
                Age   int    `xorm:"index"`   // 索引
            }

            // 使用索引字段查询
            engine.Where("email = ?", "[email protected]").Get(&user)
        b.复合索引
            type User struct {
                Name string `xorm:"index(idx_name_age)"`
                Age  int    `xorm:"index(idx_name_age)"`
            }

            // 使用复合索引
            engine.Where("name = ? AND age > ?", "Alice", 18).Find(&users)

02.查询缓存
    a.启用缓存
        a.内存缓存
            cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
            engine.SetDefaultCacher(cacher)

            // 查询自动使用缓存
            user := User{}
            engine.Id(1).Get(&user)  // 第一次查询数据库
            engine.Id(1).Get(&user)  // 第二次从缓存读取
        b.清除缓存
            // 清除指定表缓存
            engine.ClearCache(&User{})

            // 清除所有缓存
            engine.ClearCaches()

03.字段选择
    a.只查询需要的字段
        a.Cols方法
            // ❌ 查询所有字段
            engine.Find(&users)

            // ✅ 只查询需要的字段
            engine.Cols("id", "name", "email").Find(&users)
        b.Omit方法
            // 排除大字段
            engine.Omit("content", "data").Find(&articles)

04.批量查询
    a.Iterate迭代
        a.分批处理
            // 避免一次性加载大量数据
            err := engine.Where("status = ?", 0).
                Iterate(&User{}, func(i int, bean interface{}) error {
                    user := bean.(*User)
                    // 处理每条记录
                    return nil
                })

05.连接池优化
    a.连接池配置
        a.参数调优
            engine.SetMaxIdleConns(10)      // 最大空闲连接
            engine.SetMaxOpenConns(100)     // 最大打开连接
            engine.SetConnMaxLifetime(time.Hour)  // 连接生命周期
        b.监控连接
            stats := engine.DB().Stats()
            fmt.Printf("Open: %d, InUse: %d, Idle: %d\n",
                stats.OpenConnections, stats.InUse, stats.Idle)

06.性能分析
    a.SQL日志
        a.开启日志
            engine.ShowSQL(true)
            engine.Logger().SetLevel(core.LOG_DEBUG)
        b.慢查询分析
            // 记录执行时间
            start := time.Now()
            engine.Find(&users)
            duration := time.Since(start)
            if duration > time.Second {
                log.Printf("慢查询: %v", duration)
            }

5 关联关系

5.1 一对一

01.模型定义
    a.Has One
        a.用户和资料
            type User struct {
                Id   int64
                Name string
            }

            type Profile struct {
                Id     int64
                UserId int64
                Bio    string
            }
        b.外键关联
            // Profile.UserId 关联 User.Id

02.关联查询
    a.手动关联
        a.分步查询
            // 查询用户
            user := User{Id: 1}
            has, _ := engine.Get(&user)

            // 查询资料
            profile := Profile{}
            engine.Where("user_id = ?", user.Id).Get(&profile)
        b.Join查询
            type UserProfile struct {
                User    `xorm:"extends"`
                Profile `xorm:"extends"`
            }

            result := UserProfile{}
            engine.Table("user").
                Join("LEFT", "profile", "user.id = profile.user_id").
                Where("user.id = ?", 1).
                Get(&result)

03.关联创建
    a.手动创建
        a.分步插入
            // 创建用户
            user := User{Name: "Alice"}
            engine.Insert(&user)

            // 创建资料
            profile := Profile{
                UserId: user.Id,
                Bio:    "Developer",
            }
            engine.Insert(&profile)
        b.事务创建
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            user := User{Name: "Alice"}
            _, err := session.Insert(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            profile := Profile{UserId: user.Id, Bio: "Developer"}
            _, err = session.Insert(&profile)
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

04.关联更新
    a.更新关联
        a.分别更新
            // 更新用户
            user := User{Id: 1, Name: "Alice Updated"}
            engine.Id(1).Update(&user)

            // 更新资料
            profile := Profile{Bio: "Senior Developer"}
            engine.Where("user_id = ?", 1).Update(&profile)

05.关联删除
    a.手动删除
        a.级联删除
            // 删除资料
            engine.Where("user_id = ?", 1).Delete(&Profile{})

            // ���除用户
            engine.Id(1).Delete(&User{})
        b.事务删除
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            // 删除关联数据
            _, err := session.Where("user_id = ?", 1).Delete(&Profile{})
            if err != nil {
                session.Rollback()
                return err
            }

            // 删除主数据
            _, err = session.Id(1).Delete(&User{})
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

06.Belongs To
    a.多对一关联
        a.用户和公司
            type User struct {
                Id        int64
                Name      string
                CompanyId int64
            }

            type Company struct {
                Id   int64
                Name string
            }
        b.关联查询
            type UserCompany struct {
                User    `xorm:"extends"`
                Company `xorm:"extends"`
            }

            result := UserCompany{}
            engine.Table("user").
                Join("LEFT", "company", "user.company_id = company.id").
                Where("user.id = ?", 1).
                Get(&result)

5.2 一对多

01.模型定义
    a.Has Many
        a.用户和订单
            type User struct {
                Id   int64
                Name string
            }

            type Order struct {
                Id     int64
                UserId int64
                Amount float64
            }
        b.外键关联
            // Order.UserId 关联 User.Id

02.关联查询
    a.手动查询
        a.分步查询
            // 查询用户
            user := User{Id: 1}
            engine.Get(&user)

            // 查询订单
            orders := make([]Order, 0)
            engine.Where("user_id = ?", user.Id).Find(&orders)
        b.Join查询
            type UserOrder struct {
                User  `xorm:"extends"`
                Order `xorm:"extends"`
            }

            results := make([]UserOrder, 0)
            engine.Table("user").
                Join("LEFT", "order", "user.id = order.user_id").
                Where("user.id = ?", 1).
                Find(&results)

03.关联创建
    a.批量创建
        a.创建用户和订单
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            // 创建用户
            user := User{Name: "Alice"}
            _, err := session.Insert(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            // 创建多个订单
            orders := []Order{
                {UserId: user.Id, Amount: 100},
                {UserId: user.Id, Amount: 200},
                {UserId: user.Id, Amount: 300},
            }
            _, err = session.Insert(&orders)
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

04.关联统计
    a.统计关联数量
        a.Count统计
            // 统计用户的订单数
            count, err := engine.Where("user_id = ?", 1).Count(&Order{})
            fmt.Printf("User has %d orders\n", count)
        b.聚合统计
            type Result struct {
                UserId int64
                Count  int
                Total  float64
            }
            results := make([]Result, 0)
            engine.Table("order").
                Select("user_id, COUNT(*) as count, SUM(amount) as total").
                GroupBy("user_id").
                Find(&results)

05.关联更新
    a.批量更新
        a.更新关联记录
            // 更新用户的所有订单状态
            engine.Where("user_id = ?", 1).
                Update(&Order{Status: "completed"})

06.关联删除
    a.级联删除
        a.删除关联数据
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            // 删除用户的所有订单
            _, err := session.Where("user_id = ?", 1).Delete(&Order{})
            if err != nil {
                session.Rollback()
                return err
            }

            // 删除用户
            _, err = session.Id(1).Delete(&User{})
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

5.3 多对多

01.模型定义
    a.Many To Many
        a.用户和角色
            type User struct {
                Id   int64
                Name string
            }

            type Role struct {
                Id   int64
                Name string
            }

            type UserRole struct {
                Id     int64 `xorm:"pk autoincr"`
                UserId int64
                RoleId int64
            }
        b.中间表
            // UserRole 作为中间表
            // UserRole.UserId 关联 User.Id
            // UserRole.RoleId 关联 Role.Id

02.关联查询
    a.查询用户的角色
        a.Join查询
            type UserRoleResult struct {
                UserId   int64
                UserName string
                RoleId   int64
                RoleName string
            }

            results := make([]UserRoleResult, 0)
            engine.Table("user").Alias("u").
                Select("u.id as user_id, u.name as user_name, r.id as role_id, r.name as role_name").
                Join("INNER", "user_role ur", "u.id = ur.user_id").
                Join("INNER", "role r", "ur.role_id = r.id").
                Where("u.id = ?", 1).
                Find(&results)
        b.分步查询
            // 查询用户
            user := User{Id: 1}
            engine.Get(&user)

            // 查询用户角色关联
            userRoles := make([]UserRole, 0)
            engine.Where("user_id = ?", user.Id).Find(&userRoles)

            // 查询角色详情
            roleIds := make([]int64, 0)
            for _, ur := range userRoles {
                roleIds = append(roleIds, ur.RoleId)
            }

            roles := make([]Role, 0)
            engine.In("id", roleIds).Find(&roles)

03.关联创建
    a.添加关联
        a.创建关联记录
            // 为用户添加角色
            userRole := UserRole{
                UserId: 1,
                RoleId: 2,
            }
            engine.Insert(&userRole)
        b.批量添加
            userRoles := []UserRole{
                {UserId: 1, RoleId: 1},
                {UserId: 1, RoleId: 2},
                {UserId: 1, RoleId: 3},
            }
            engine.Insert(&userRoles)

04.关联删除
    a.删除关联
        a.删除指定关联
            // 删除用户的某个角色
            engine.Where("user_id = ? AND role_id = ?", 1, 2).Delete(&UserRole{})
        b.清空关联
            // 删除用户的所有角色
            engine.Where("user_id = ?", 1).Delete(&UserRole{})

05.关联更新
    a.替换关联
        a.更新用户角色
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            // 删除旧关联
            _, err := session.Where("user_id = ?", 1).Delete(&UserRole{})
            if err != nil {
                session.Rollback()
                return err
            }

            // 添加新关联
            newRoles := []UserRole{
                {UserId: 1, RoleId: 3},
                {UserId: 1, RoleId: 4},
            }
            _, err = session.Insert(&newRoles)
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

06.中间表扩展
    a.带额外字段的中间表
        a.扩展中间表
            type UserRole struct {
                Id        int64     `xorm:"pk autoincr"`
                UserId    int64
                RoleId    int64
                CreatedAt time.Time `xorm:"created"`
                CreatedBy int64
            }

            // 创建关联时设置额外字段
            userRole := UserRole{
                UserId:    1,
                RoleId:    2,
                CreatedBy: 100,
            }
            engine.Insert(&userRole)

5.4 关联查询

01.Join策略
    a.Inner Join
        a.内连接查询
            type UserOrder struct {
                User  `xorm:"extends"`
                Order `xorm:"extends"`
            }

            results := make([]UserOrder, 0)
            engine.Table("user").
                Join("INNER", "order", "user.id = order.user_id").
                Where("user.age > ?", 18).
                Find(&results)
        b.性能特点
            // Inner Join适用于:
            // 1. 必须有关联数据的场景
            // 2. 一对一关联
            // 3. 数据量较小的关联

02.Left Join
    a.左连接查询
        a.保留主表数据
            results := make([]UserOrder, 0)
            engine.Table("user").
                Join("LEFT", "order", "user.id = order.user_id").
                Find(&results)
            // 返回所有用户,包括没有订单的用户
        b.使用场景
            // Left Join适用于:
            // 1. 需要保留主表所有数据
            // 2. 一对多关联
            // 3. 关联数据可能不存在

03.多表关联
    a.三表关联
        a.用户-订单-商品
            type UserOrderProduct struct {
                UserId      int64
                UserName    string
                OrderId     int64
                OrderAmount float64
                ProductId   int64
                ProductName string
            }

            results := make([]UserOrderProduct, 0)
            engine.Table("user").Alias("u").
                Select(`
                    u.id as user_id,
                    u.name as user_name,
                    o.id as order_id,
                    o.amount as order_amount,
                    p.id as product_id,
                    p.name as product_name
                `).
                Join("LEFT", "order o", "u.id = o.user_id").
                Join("LEFT", "product p", "o.product_id = p.id").
                Find(&results)

04.条件关联
    a.关联条件过滤
        a.Join条件
            // 只关联已支付的订单
            results := make([]UserOrder, 0)
            engine.Table("user").
                Join("LEFT", "order", "user.id = order.user_id AND order.status = 'paid'").
                Find(&results)
        b.Where条件
            engine.Table("user").
                Join("LEFT", "order", "user.id = order.user_id").
                Where("order.amount > ?", 100).
                Find(&results)

05.关联统计
    a.统计关联数据
        a.Count统计
            type UserOrderCount struct {
                UserId     int64
                UserName   string
                OrderCount int
            }

            results := make([]UserOrderCount, 0)
            engine.Table("user").Alias("u").
                Select("u.id as user_id, u.name as user_name, COUNT(o.id) as order_count").
                Join("LEFT", "order o", "u.id = o.user_id").
                GroupBy("u.id").
                Find(&results)
        b.聚合统计
            type UserOrderStats struct {
                UserId     int64
                OrderCount int
                TotalAmount float64
                AvgAmount   float64
            }

            results := make([]UserOrderStats, 0)
            engine.Table("user").Alias("u").
                Select(`
                    u.id as user_id,
                    COUNT(o.id) as order_count,
                    SUM(o.amount) as total_amount,
                    AVG(o.amount) as avg_amount
                `).
                Join("LEFT", "order o", "u.id = o.user_id").
                GroupBy("u.id").
                Having("COUNT(o.id) > ?", 5).
                Find(&results)

06.性能优化
    a.优化建议
        a.索引优化
            // 确保关联字段有索引
            type Order struct {
                Id     int64
                UserId int64 `xorm:"index"`  // 外键索引
                Amount float64
            }
        b.字段选择
            // 只查询需要的字段
            engine.Table("user").Alias("u").
                Cols("u.id", "u.name", "o.amount").
                Join("LEFT", "order o", "u.id = o.user_id").
                Find(&results)
        c.分页查询
            // 大数据量时使用分页
            engine.Table("user").
                Join("LEFT", "order", "user.id = order.user_id").
                Limit(100, 0).
                Find(&results)

5.5 级联操作

01.级联插入
    a.手动级联
        a.事务插入
            session := engine.NewSession()
            defer session.Close()

            err := session.Begin()
            if err != nil {
                return err
            }

            // 插入用户
            user := User{Name: "Alice", Email: "[email protected]"}
            _, err = session.Insert(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            // 插入资料
            profile := Profile{UserId: user.Id, Bio: "Developer"}
            _, err = session.Insert(&profile)
            if err != nil {
                session.Rollback()
                return err
            }

            // 插入订单
            orders := []Order{
                {UserId: user.Id, Amount: 100},
                {UserId: user.Id, Amount: 200},
            }
            _, err = session.Insert(&orders)
            if err != nil {
                session.Rollback()
                return err
            }

            return session.Commit()

02.级联更新
    a.更新关联数据
        a.事务更新
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            // 更新用户
            user := User{Id: 1, Name: "Alice Updated"}
            _, err := session.Id(1).Update(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            // 更新关联的资料
            profile := Profile{Bio: "Senior Developer"}
            _, err = session.Where("user_id = ?", 1).Update(&profile)
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

03.级联删除
    a.删除关联数据
        a.事务删除
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            userId := int64(1)

            // 删除用户角色关联
            _, err := session.Where("user_id = ?", userId).Delete(&UserRole{})
            if err != nil {
                session.Rollback()
                return err
            }

            // 删除用户订单
            _, err = session.Where("user_id = ?", userId).Delete(&Order{})
            if err != nil {
                session.Rollback()
                return err
            }

            // 删除用户资料
            _, err = session.Where("user_id = ?", userId).Delete(&Profile{})
            if err != nil {
                session.Rollback()
                return err
            }

            // 删除用户
            _, err = session.Id(userId).Delete(&User{})
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

04.级联查询
    a.多层级查询
        a.查询用户及关联
            // 查询用户
            user := User{Id: 1}
            engine.Get(&user)

            // 查询资料
            profile := Profile{}
            engine.Where("user_id = ?", user.Id).Get(&profile)

            // 查询订单
            orders := make([]Order, 0)
            engine.Where("user_id = ?", user.Id).Find(&orders)

            // 查询角色
            userRoles := make([]UserRole, 0)
            engine.Where("user_id = ?", user.Id).Find(&userRoles)

            roleIds := make([]int64, 0)
            for _, ur := range userRoles {
                roleIds = append(roleIds, ur.RoleId)
            }

            roles := make([]Role, 0)
            if len(roleIds) > 0 {
                engine.In("id", roleIds).Find(&roles)
            }

05.级联封装
    a.封装级联操作
        a.级联删除函数
            func DeleteUserCascade(engine *xorm.Engine, userId int64) error {
                session := engine.NewSession()
                defer session.Close()

                if err := session.Begin(); err != nil {
                    return err
                }

                // 删除关联表
                tables := []interface{}{
                    &UserRole{},
                    &Order{},
                    &Profile{},
                }

                for _, table := range tables {
                    if _, err := session.Where("user_id = ?", userId).Delete(table); err != nil {
                        session.Rollback()
                        return err
                    }
                }

                // 删除主表
                if _, err := session.Id(userId).Delete(&User{}); err != nil {
                    session.Rollback()
                    return err
                }

                return session.Commit()
            }

06.注意事项
    a.事务使用
        a.必须使用事务
            // ✅ 正确:使用事务保证一致性
            session := engine.NewSession()
            session.Begin()
            // ... 级联操作
            session.Commit()

            // ❌ 错误:不使用事务
            engine.Delete(&Profile{})
            engine.Delete(&User{})  // 可能导致数据不一致
        b.错误处理
            // 任何步骤失败都要回滚
            if err != nil {
                session.Rollback()
                return err
            }

5.6 关联缓存

01.缓存配置
    a.启用缓存
        a.全局缓存
            cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
            engine.SetDefaultCacher(cacher)
        b.表级缓存
            // 为特定表启用缓存
            engine.MapCacher(&User{}, xorm.NewLRUCacher(xorm.NewMemoryStore(), 500))

02.关联查询缓存
    a.缓存关联数据
        a.主表缓存
            // 用户查询使用缓存
            user := User{Id: 1}
            engine.Get(&user)  // 第一次查询数据库
            engine.Get(&user)  // 第二次从缓存读取
        b.关联表缓存
            // 订单查询使用缓存
            orders := make([]Order, 0)
            engine.Where("user_id = ?", 1).Find(&orders)  // 第一次查询数据库
            engine.Where("user_id = ?", 1).Find(&orders)  // 第二次从缓存读取

03.缓存失效
    a.自动失效
        a.更新失效
            // 更新时自动清除缓存
            user := User{Id: 1, Name: "Updated"}
            engine.Id(1).Update(&user)  // 自动清除user表缓存
        b.删除失效
            // 删除时自动清除缓存
            engine.Id(1).Delete(&User{})  // 自动清除user表缓存

04.手动清除
    a.清除缓存
        a.清除表缓存
            // 清除指定表缓存
            engine.ClearCache(&User{})
            engine.ClearCache(&Order{})
        b.清除所有缓存
            // 清除所有表缓存
            engine.ClearCaches()

05.缓存策略
    a.缓存选择
        a.适合缓存的场景
            // 1. 读多写少的数据
            // 2. 查询频繁的数据
            // 3. 数据变化不频繁
            engine.MapCacher(&Config{}, cacher)
            engine.MapCacher(&Category{}, cacher)
        b.不适合缓存的场景
            // 1. 实时性要求高的数据
            // 2. 频繁更新的数据
            // 3. 大数据量查询
            engine.MapCacher(&Order{}, nil)  // 禁用缓存

06.缓存优化
    a.缓存大小
        a.设置缓存容量
            // 根据数据量设置合适的缓存大小
            cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 10000)
            engine.SetDefaultCacher(cacher)
        b.分表缓存
            // 不同表使用不同大小的缓存
            engine.MapCacher(&User{}, xorm.NewLRUCacher(xorm.NewMemoryStore(), 5000))
            engine.MapCacher(&Order{}, xorm.NewLRUCacher(xorm.NewMemoryStore(), 10000))

6 事务与迁移

6.1 事务处理

01.手动事务
    a.基础事务
        a.Begin/Commit
            session := engine.NewSession()
            defer session.Close()

            err := session.Begin()
            if err != nil {
                return err
            }

            // 执行操作
            _, err = session.Insert(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            _, err = session.Insert(&order)
            if err != nil {
                session.Rollback()
                return err
            }

            // 提交事务
            err = session.Commit()
            if err != nil {
                return err
            }

02.事务封装
    a.事务函数
        a.封装事务逻辑
            func TransferMoney(engine *xorm.Engine, fromId, toId int64, amount float64) error {
                session := engine.NewSession()
                defer session.Close()

                if err := session.Begin(); err != nil {
                    return err
                }

                // 扣款
                _, err := session.Exec("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId)
                if err != nil {
                    session.Rollback()
                    return err
                }

                // 加款
                _, err = session.Exec("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId)
                if err != nil {
                    session.Rollback()
                    return err
                }

                return session.Commit()
            }

03.嵌套事务
    a.SavePoint
        a.保存点
            session := engine.NewSession()
            defer session.Close()

            session.Begin()

            // 第一步操作
            session.Insert(&user)

            // 创建保存点
            // xorm不直接支持SavePoint
            // 需要使用原生SQL
            session.Exec("SAVEPOINT sp1")

            // 第二步操作
            _, err := session.Insert(&order)
            if err != nil {
                // 回滚到保存点
                session.Exec("ROLLBACK TO SAVEPOINT sp1")
            }

            session.Commit()

04.事务隔离
    a.隔离级别
        a.设置隔离级别
            session := engine.NewSession()
            defer session.Close()

            // 设置隔离级别
            session.Exec("SET TRANSACTION ISOLATION LEVEL READ COMMITTED")

            session.Begin()
            // ... 事务操作
            session.Commit()
        b.隔离级别说明
            // READ UNCOMMITTED: 读未提交
            // READ COMMITTED: 读已提交
            // REPEATABLE READ: 可重复读
            // SERIALIZABLE: 串行化

05.事务超时
    a.超时控制
        a.设置超时
            session := engine.NewSession()
            defer session.Close()

            // 设置超时时间
            ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
            defer cancel()

            session.Context(ctx)
            session.Begin()

            // 执行操作
            _, err := session.Insert(&user)
            if err != nil {
                session.Rollback()
                return err
            }

            session.Commit()

06.事务最佳实践
    a.使用建议
        a.事务范围
            // ✅ 正确:事务范围尽可能小
            session.Begin()
            session.Insert(&user)
            session.Insert(&order)
            session.Commit()

            // ❌ 错误:事务范围过大
            session.Begin()
            // 大量业务逻辑
            // 网络请求
            // 文件操作
            session.Commit()
        b.错误处理
            // ✅ 正确:使用defer确保关闭
            session := engine.NewSession()
            defer session.Close()

            // ✅ 正确:错误时回滚
            if err != nil {
                session.Rollback()
                return err
            }
        c.避免死锁
            // 1. 按相同顺序访问资源
            // 2. 缩短事务时间
            // 3. 使用合适的隔离级别

6.2 同步结构

01.Sync2方法
    a.自动同步
        a.同步单表
            // 同步User表结构
            err := engine.Sync2(new(User))
            if err != nil {
                log.Fatal(err)
            }
        b.同步多表
            // 同步多个表
            err := engine.Sync2(
                new(User),
                new(Order),
                new(Product),
                new(Category),
            )

02.同步规则
    a.同步行为
        a.会执行的操作
            // 1. 创建不存在的表
            // 2. 添加缺失的字段
            // 3. 创建缺失的索引
            // 4. 更新字段注释
        b.不会执行的操作
            // 1. 删除字段
            // 2. 修改字段类型
            // 3. 删除索引
            // 4. 删除表

03.表选项
    a.表引擎
        a.设置表引擎
            // MySQL设置InnoDB引擎
            engine.StoreEngine("InnoDB")

            // 同步时应用
            engine.Sync2(new(User))
        b.字符集
            // 设置字符集
            engine.Charset("utf8mb4")

04.索引同步
    a.索引创建
        a.自动创建索引
            type User struct {
                Id    int64  `xorm:"pk autoincr"`
                Name  string `xorm:"index"`
                Email string `xorm:"unique"`
            }

            // Sync2会自动创建索引
            engine.Sync2(new(User))

05.字段变更
    a.添加字段
        a.新增字段
            // 原模型
            type User struct {
                Id   int64
                Name string
            }

            // 新模型(添加Email字段)
            type User struct {
                Id    int64
                Name  string
                Email string `xorm:"varchar(100)"`
            }

            // 同步会自动添加Email字段
            engine.Sync2(new(User))

06.注意事项
    a.生产环境
        a.使用建议
            // 1. 开发环境可以使用Sync2
            // 2. 生产环境建议使用迁移工具
            // 3. 先在测试环境验证
            // 4. 做好数据备份
        b.风险提示
            // 1. Sync2不会删除字段
            // 2. 不会修改字段类型
            // 3. 可能导致数据不一致

6.3 手动迁移

01.CreateTables
    a.创建表
        a.手动创建
            // 创建单个表
            err := engine.CreateTables(new(User))

            // 创建多个表
            err := engine.CreateTables(new(User), new(Order))
        b.检查表是否存在
            exists, err := engine.IsTableExist("user")
            if !exists {
                engine.CreateTables(new(User))
            }

02.DropTables
    a.删除表
        a.删除表
            // 删除单个表
            err := engine.DropTables(new(User))

            // 删除多个表
            err := engine.DropTables(new(User), new(Order))
        b.安全删除
            // 先检查再删除
            exists, _ := engine.IsTableExist("user")
            if exists {
                engine.DropTables(new(User))
            }

03.CreateIndexes
    a.创建索引
        a.手动创建索引
            // 创建表的所有索引
            err := engine.CreateIndexes(new(User))
        b.创建单个索引
            // 使用原生SQL创建索引
            _, err := engine.Exec("CREATE INDEX idx_email ON user(email)")

04.CreateUniques
    a.创建唯一索引
        a.创建唯一约束
            // 创建表的所有唯一索引
            err := engine.CreateUniques(new(User))

05.迁移脚本
    a.版本管理
        a.迁移文件
            // migrations/001_create_users.go
            func Migration001(engine *xorm.Engine) error {
                type User struct {
                    Id    int64  `xorm:"pk autoincr"`
                    Name  string `xorm:"varchar(100) notnull"`
                    Email string `xorm:"varchar(100) unique"`
                }
                return engine.Sync2(new(User))
            }

            // migrations/002_add_user_age.go
            func Migration002(engine *xorm.Engine) error {
                _, err := engine.Exec("ALTER TABLE user ADD COLUMN age INT DEFAULT 0")
                return err
            }
        b.迁移管理
            type Migration struct {
                Id        int64     `xorm:"pk autoincr"`
                Version   string    `xorm:"varchar(50) unique"`
                AppliedAt time.Time `xorm:"created"`
            }

            func RunMigrations(engine *xorm.Engine) error {
                // 创建迁移记录表
                engine.Sync2(new(Migration))

                migrations := []struct {
                    Version string
                    Fn      func(*xorm.Engine) error
                }{
                    {"001", Migration001},
                    {"002", Migration002},
                }

                for _, m := range migrations {
                    // 检查是否已执行
                    exists, _ := engine.Where("version = ?", m.Version).Exist(&Migration{})
                    if exists {
                        continue
                    }

                    // 执行迁移
                    if err := m.Fn(engine); err != nil {
                        return err
                    }

                    // 记录迁移
                    engine.Insert(&Migration{Version: m.Version})
                }

                return nil
            }

06.回滚支持
    a.回滚脚本
        a.Up/Down迁移
            // migrations/003_add_user_status.go
            func Migration003Up(engine *xorm.Engine) error {
                _, err := engine.Exec("ALTER TABLE user ADD COLUMN status INT DEFAULT 1")
                return err
            }

            func Migration003Down(engine *xorm.Engine) error {
                _, err := engine.Exec("ALTER TABLE user DROP COLUMN status")
                return err
            }

6.4 数据导入导出

01.数据导出
    a.导出到CSV
        a.CSV导出
            import "encoding/csv"

            func ExportToCSV(engine *xorm.Engine, filename string) error {
                file, err := os.Create(filename)
                if err != nil {
                    return err
                }
                defer file.Close()

                writer := csv.NewWriter(file)
                defer writer.Flush()

                // 写入表头
                writer.Write([]string{"ID", "Name", "Email", "Age"})

                // 查询数据
                users := make([]User, 0)
                err = engine.Find(&users)
                if err != nil {
                    return err
                }

                // 写入数据
                for _, user := range users {
                    writer.Write([]string{
                        fmt.Sprintf("%d", user.Id),
                        user.Name,
                        user.Email,
                        fmt.Sprintf("%d", user.Age),
                    })
                }

                return nil
            }

02.数据导入
    a.从CSV导入
        a.CSV导入
            import "encoding/csv"

            func ImportFromCSV(engine *xorm.Engine, filename string) error {
                file, err := os.Open(filename)
                if err != nil {
                    return err
                }
                defer file.Close()

                reader := csv.NewReader(file)
                records, err := reader.ReadAll()
                if err != nil {
                    return err
                }

                users := make([]User, 0)
                for i, record := range records {
                    if i == 0 {
                        continue  // 跳过表头
                    }

                    age, _ := strconv.Atoi(record[3])
                    users = append(users, User{
                        Name:  record,
                        Email: record,
                        Age:   age,
                    })
                }

                // 批量插入
                _, err = engine.Insert(&users)
                return err
            }

03.JSON导出
    a.导出JSON
        a.JSON格式
            import "encoding/json"

            func ExportToJSON(engine *xorm.Engine, filename string) error {
                users := make([]User, 0)
                err := engine.Find(&users)
                if err != nil {
                    return err
                }

                data, err := json.MarshalIndent(users, "", "  ")
                if err != nil {
                    return err
                }

                return os.WriteFile(filename, data, 0644)
            }

04.JSON导入
    a.从JSON导入
        a.JSON格式
            import "encoding/json"

            func ImportFromJSON(engine *xorm.Engine, filename string) error {
                data, err := os.ReadFile(filename)
                if err != nil {
                    return err
                }

                users := make([]User, 0)
                err = json.Unmarshal(data, &users)
                if err != nil {
                    return err
                }

                // 批量插入
                _, err = engine.Insert(&users)
                return err
            }

05.SQL导出
    a.导出SQL
        a.Dump数据
            func DumpToSQL(engine *xorm.Engine, filename string) error {
                file, err := os.Create(filename)
                if err != nil {
                    return err
                }
                defer file.Close()

                users := make([]User, 0)
                engine.Find(&users)

                for _, user := range users {
                    sql := fmt.Sprintf(
                        "INSERT INTO user (name, email, age) VALUES ('%s', '%s', %d);\n",
                        user.Name, user.Email, user.Age,
                    )
                    file.WriteString(sql)
                }

                return nil
            }

06.批量导入优化
    a.分批导入
        a.性能优化
            func ImportLargeData(engine *xorm.Engine, data []User) error {
                batchSize := 1000

                for i := 0; i < len(data); i += batchSize {
                    end := i + batchSize
                    if end > len(data) {
                        end = len(data)
                    }

                    batch := data[i:end]
                    _, err := engine.Insert(&batch)
                    if err != nil {
                        return err
                    }

                    fmt.Printf("Imported %d/%d records\n", end, len(data))
                }

                return nil
            }

6.5 版本管理

01.迁移表
    a.版本记录
        a.迁移记录表
            type Migration struct {
                Id          int64     `xorm:"pk autoincr"`
                Version     string    `xorm:"varchar(50) unique notnull"`
                Description string    `xorm:"varchar(200)"`
                AppliedAt   time.Time `xorm:"created"`
            }

            // 初始化迁移表
            func InitMigrationTable(engine *xorm.Engine) error {
                return engine.Sync2(new(Migration))
            }

02.迁移管理器
    a.迁移执行器
        a.迁移管理
            type MigrationManager struct {
                engine     *xorm.Engine
                migrations []MigrationItem
            }

            type MigrationItem struct {
                Version     string
                Description string
                Up          func(*xorm.Engine) error
                Down        func(*xorm.Engine) error
            }

            func NewMigrationManager(engine *xorm.Engine) *MigrationManager {
                return &MigrationManager{
                    engine:     engine,
                    migrations: make([]MigrationItem, 0),
                }
            }

            func (m *MigrationManager) Register(item MigrationItem) {
                m.migrations = append(m.migrations, item)
            }

            func (m *MigrationManager) Up() error {
                // 确保迁移表存在
                m.engine.Sync2(new(Migration))

                for _, item := range m.migrations {
                    // 检查是否已执行
                    exists, _ := m.engine.Where("version = ?", item.Version).Exist(&Migration{})
                    if exists {
                        fmt.Printf("Migration %s already applied\n", item.Version)
                        continue
                    }

                    // 执行迁移
                    fmt.Printf("Applying migration %s: %s\n", item.Version, item.Description)
                    if err := item.Up(m.engine); err != nil {
                        return fmt.Errorf("migration %s failed: %v", item.Version, err)
                    }

                    // 记录迁移
                    migration := Migration{
                        Version:     item.Version,
                        Description: item.Description,
                    }
                    m.engine.Insert(&migration)

                    fmt.Printf("Migration %s applied successfully\n", item.Version)
                }

                return nil
            }

            func (m *MigrationManager) Down(version string) error {
                // 查找迁移
                var item *MigrationItem
                for i := range m.migrations {
                    if m.migrations[i].Version == version {
                        item = &m.migrations[i]
                        break
                    }
                }

                if item == nil {
                    return fmt.Errorf("migration %s not found", version)
                }

                // 执行回滚
                fmt.Printf("Rolling back migration %s\n", version)
                if err := item.Down(m.engine); err != nil {
                    return err
                }

                // 删除迁移记录
                m.engine.Where("version = ?", version).Delete(&Migration{})

                fmt.Printf("Migration %s rolled back successfully\n", version)
                return nil
            }

03.迁移示例
    a.定义迁移
        a.迁移文件
            // 001_create_users_table.go
            var Migration001 = MigrationItem{
                Version:     "001",
                Description: "Create users table",
                Up: func(engine *xorm.Engine) error {
                    type User struct {
                        Id    int64  `xorm:"pk autoincr"`
                        Name  string `xorm:"varchar(100) notnull"`
                        Email string `xorm:"varchar(100) unique"`
                    }
                    return engine.Sync2(new(User))
                },
                Down: func(engine *xorm.Engine) error {
                    return engine.DropTables("user")
                },
            }

            // 002_add_user_age.go
            var Migration002 = MigrationItem{
                Version:     "002",
                Description: "Add age column to users table",
                Up: func(engine *xorm.Engine) error {
                    _, err := engine.Exec("ALTER TABLE user ADD COLUMN age INT DEFAULT 0")
                    return err
                },
                Down: func(engine *xorm.Engine) error {
                    _, err := engine.Exec("ALTER TABLE user DROP COLUMN age")
                    return err
                },
            }

04.使用迁移
    a.执行迁移
        a.主程序
            func main() {
                engine, _ := xorm.NewEngine("mysql", dsn)

                // 创建迁移管理器
                manager := NewMigrationManager(engine)

                // 注册迁移
                manager.Register(Migration001)
                manager.Register(Migration002)

                // 执行所有迁移
                if err := manager.Up(); err != nil {
                    log.Fatal(err)
                }

                // 回滚指定迁移
                // manager.Down("002")
            }

05.团队协作
    a.迁移规范
        a.命名规范
            // 迁移文件命名:{version}_{description}.go
            // 001_create_users_table.go
            // 002_add_user_age.go
            // 003_create_orders_table.go
        b.版本号规则
            // 1. 使用递增的数字版本号
            // 2. 或使用时间戳:20240101120000
            // 3. 避免版本号冲突
        c.提交规范
            // 1. 迁移文件随代码一起提交
            // 2. 先拉取最新代码再创建迁移
            // 3. 迁移文件一旦合并不要修改

06.生产部署
    a.部署流程
        a.部署步骤
            // 1. 备份数据库
            mysqldump -u user -p dbname > backup.sql

            // 2. 在测试环境验证迁移
            manager.Up()

            // 3. 生产环境执行迁移
            manager.Up()

            // 4. 验证迁移结果
            // 检查表结构和数据

            // 5. 如有问题立即回滚
            manager.Down("version")
        b.回滚策略
            // 1. 代码回滚:回滚到上一版本
            // 2. 数据库回滚:执行Down迁移
            // 3. 数据恢复:从备份恢复

7 高级特性

7.1 缓存机制

01.缓存配置
    a.内存缓存
        a.LRU缓存
            import "xorm.io/xorm/caches"

            // 创建LRU缓存
            cacher := caches.NewLRUCacher(caches.NewMemoryStore(), 1000)

            // 设置全局缓存
            engine.SetDefaultCacher(cacher)
        b.缓存容量
            // 设置不同容量的缓存
            smallCacher := caches.NewLRUCacher(caches.NewMemoryStore(), 100)
            largeCacher := caches.NewLRUCacher(caches.NewMemoryStore(), 10000)

02.表级缓存
    a.为特定表设置缓存
        a.单表缓存
            // 为User表设置缓存
            userCacher := caches.NewLRUCacher(caches.NewMemoryStore(), 500)
            engine.MapCacher(&User{}, userCacher)

            // 为Order表设置缓存
            orderCacher := caches.NewLRUCacher(caches.NewMemoryStore(), 1000)
            engine.MapCacher(&Order{}, orderCacher)
        b.禁用缓存
            // 禁用特定表的缓存
            engine.MapCacher(&Log{}, nil)

03.缓存使用
    a.自动缓存
        a.查询缓存
            // 第一次查询数据库
            user := User{Id: 1}
            has, _ := engine.Get(&user)

            // 第二次从缓存读取
            user2 := User{Id: 1}
            has, _ = engine.Get(&user2)  // 从缓存读取
        b.条件查询缓存
            users := make([]User, 0)
            // 第一次查询数据库
            engine.Where("age > ?", 18).Find(&users)

            // 第二次从缓存读取(相同条件)
            engine.Where("age > ?", 18).Find(&users)

04.缓存失效
    a.自动失效
        a.更新失效
            // 更新时自动清除缓存
            user := User{Id: 1, Name: "Updated"}
            engine.Id(1).Update(&user)  // 自动清除缓存
        b.删除失效
            // 删除时自动清除缓存
            engine.Id(1).Delete(&User{})  // 自动清除缓存
        c.插入失效
            // 插入时自动清除缓存
            user := User{Name: "New User"}
            engine.Insert(&user)  // 自动清除缓存

05.手动清除
    a.清除缓存
        a.清除表缓存
            // 清除User表的所有缓存
            engine.ClearCache(&User{})
        b.清除所有缓存
            // 清除所有表的缓存
            engine.ClearCaches()

06.缓存策略
    a.适用场景
        a.适合缓存
            // 1. 读多写少的数据
            type Config struct {
                Id    int64
                Key   string
                Value string
            }
            engine.MapCacher(&Config{}, cacher)

            // 2. 查询频繁的数据
            type Category struct {
                Id   int64
                Name string
            }
            engine.MapCacher(&Category{}, cacher)

            // 3. 数据变化不频繁
            type Dictionary struct {
                Id   int64
                Code string
                Name string
            }
            engine.MapCacher(&Dictionary{}, cacher)
        b.不适合缓存
            // 1. 实时性要求高
            type Order struct {
                Id     int64
                Status string
            }
            engine.MapCacher(&Order{}, nil)  // 禁用缓存

            // 2. 频繁更新的数据
            type Log struct {
                Id      int64
                Message string
            }
            engine.MapCacher(&Log{}, nil)

            // 3. 大数据量查询
            // 不要缓存大结果集

7.2 性能优化

01.连接池优化
    a.连接池配置
        a.参数调优
            engine.SetMaxIdleConns(10)      // 最大空闲连接数
            engine.SetMaxOpenConns(100)     // 最大打开连接数
            engine.SetConnMaxLifetime(time.Hour)  // 连接最大生命周期
        b.监控连接
            stats := engine.DB().Stats()
            log.Printf("Open: %d, InUse: %d, Idle: %d",
                stats.OpenConnections, stats.InUse, stats.Idle)

02.查询优化
    a.索引优化
        a.添加索引
            type User struct {
                Id    int64  `xorm:"pk autoincr"`
                Name  string `xorm:"index"`
                Email string `xorm:"unique"`
                Age   int    `xorm:"index"`
            }

            // 复合索引
            type Order struct {
                Id     int64 `xorm:"pk autoincr"`
                UserId int64 `xorm:"index(idx_user_status)"`
                Status int   `xorm:"index(idx_user_status)"`
            }
        b.使用索引
            // ✅ 使用索引字段查询
            engine.Where("email = ?", "[email protected]").Get(&user)

            // ❌ 避免在索引字段上使用函数
            engine.Where("UPPER(email) = ?", "[email protected]").Get(&user)

03.字段选择
    a.只查询需要的字段
        a.Cols方法
            // ❌ 查询所有字段
            engine.Find(&users)

            // ✅ 只查询需要的字段
            engine.Cols("id", "name", "email").Find(&users)
        b.Omit方法
            // 排除大字段
            engine.Omit("content", "data", "description").Find(&articles)

04.批量操作
    a.批量插入
        a.分批插入
            users := make([]User, 10000)
            // ... 填充数据

            batchSize := 1000
            for i := 0; i < len(users); i += batchSize {
                end := i + batchSize
                if end > len(users) {
                    end = len(users)
                }
                batch := users[i:end]
                engine.Insert(&batch)
            }
        b.事务批量
            session := engine.NewSession()
            defer session.Close()

            session.Begin()
            for _, user := range users {
                session.Insert(&user)
            }
            session.Commit()

05.Iterate优化
    a.迭代处理
        a.避免大结果集
            // ❌ 一次性加载所有数据
            users := make([]User, 0)
            engine.Find(&users)

            // ✅ 使用Iterate逐行处理
            engine.Iterate(&User{}, func(i int, bean interface{}) error {
                user := bean.(*User)
                // 处理每条记录
                return nil
            })

06.缓存优化
    a.启用缓存
        a.查询缓存
            cacher := caches.NewLRUCacher(caches.NewMemoryStore(), 1000)
            engine.SetDefaultCacher(cacher)

            // 查询自动使用缓存
            engine.Id(1).Get(&user)
        b.缓存大小
            // 根据数据量设置合适的缓存大小
            engine.MapCacher(&User{}, caches.NewLRUCacher(caches.NewMemoryStore(), 5000))
            engine.MapCacher(&Order{}, caches.NewLRUCacher(caches.NewMemoryStore(), 10000))

7.3 连接池

01.连接池配置
    a.基础配置
        a.参数设置
            engine.SetMaxIdleConns(10)      // 最大空闲连接数
            engine.SetMaxOpenConns(100)     // 最大打开连接数
            engine.SetConnMaxLifetime(time.Hour)  // 连接最大生命周期
        b.配置说明
            // MaxIdleConns: 连接池中保持的最大空闲连接数
            // MaxOpenConns: 数据库的最大打开连接数
            // ConnMaxLifetime: 连接可重用的最长时间

02.连接监控
    a.Stats监控
        a.连接状态
            stats := engine.DB().Stats()
            fmt.Printf("OpenConnections: %d\n", stats.OpenConnections)
            fmt.Printf("InUse: %d\n", stats.InUse)
            fmt.Printf("Idle: %d\n", stats.Idle)
            fmt.Printf("WaitCount: %d\n", stats.WaitCount)
            fmt.Printf("WaitDuration: %v\n", stats.WaitDuration)
        b.定期监控
            ticker := time.NewTicker(1 * time.Minute)
            go func() {
                for range ticker.C {
                    stats := engine.DB().Stats()
                    if stats.OpenConnections > 80 {
                        log.Warn("连接数过高:", stats.OpenConnections)
                    }
                    if stats.WaitCount > 100 {
                        log.Warn("等待连接次数过多:", stats.WaitCount)
                    }
                }
            }()

03.连接泄漏
    a.检测泄漏
        a.连接检查
            // 定期检查连接数
            func CheckConnectionLeak(engine *xorm.Engine) {
                stats := engine.DB().Stats()
                if stats.InUse > stats.MaxOpenConns*80/100 {
                    log.Error("可能存在连接泄漏")
                }
            }
        b.预防泄漏
            // ✅ 正确:使用defer关闭session
            session := engine.NewSession()
            defer session.Close()

            // ❌ 错误:忘记关闭session
            session := engine.NewSession()
            session.Insert(&user)

04.性能调优
    a.参数调优
        a.根据场景调整
            // 高并发场景
            engine.SetMaxIdleConns(50)
            engine.SetMaxOpenConns(200)
            engine.SetConnMaxLifetime(30 * time.Minute)

            // 低并发场景
            engine.SetMaxIdleConns(5)
            engine.SetMaxOpenConns(20)
            engine.SetConnMaxLifetime(1 * time.Hour)
        b.计算公式
            // MaxOpenConns = (核心数 * 2) + 磁盘数
            // MaxIdleConns = MaxOpenConns / 2

05.连接超时
    a.超时设置
        a.连接超时
            // MySQL DSN中设置超时
            dsn := "user:pass@tcp(host:port)/db?timeout=5s&readTimeout=10s&writeTimeout=10s"
            engine, _ := xorm.NewEngine("mysql", dsn)
        b.Context超时
            ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
            defer cancel()

            session := engine.NewSession()
            defer session.Close()

            session.Context(ctx)
            session.Get(&user)

06.最佳实践
    a.使用建议
        a.���接管理
            // 1. 合理设置连接池大小
            // 2. 监控连接使用情况
            // 3. 及时关闭session
            // 4. 避免长时间持有连接
        b.错误处理
            // 检查连接是否可用
            err := engine.Ping()
            if err != nil {
                log.Error("数据库连接失败:", err)
                // 重新连接
            }

7.4 读写分离

01.主从配置
    a.多引擎配置
        a.主从引擎
            // 主库引擎
            masterEngine, err := xorm.NewEngine("mysql", masterDSN)
            if err != nil {
                log.Fatal(err)
            }

            // 从库引擎
            slaveEngine, err := xorm.NewEngine("mysql", slaveDSN)
            if err != nil {
                log.Fatal(err)
            }
        b.多个从库
            // 主库
            masterEngine, _ := xorm.NewEngine("mysql", masterDSN)

            // 从库1
            slave1Engine, _ := xorm.NewEngine("mysql", slave1DSN)

            // 从库2
            slave2Engine, _ := xorm.NewEngine("mysql", slave2DSN)

02.读写策略
    a.手动路由
        a.写操作用主库
            // 写操作使用主库
            user := User{Name: "Alice", Email: "[email protected]"}
            masterEngine.Insert(&user)

            user.Name = "Alice Updated"
            masterEngine.Id(user.Id).Update(&user)

            masterEngine.Id(user.Id).Delete(&User{})
        b.���操作用从库
            // 读操作使用从库
            users := make([]User, 0)
            slaveEngine.Find(&users)

            user := User{Id: 1}
            slaveEngine.Get(&user)

            count, _ := slaveEngine.Count(&User{})

03.负载均衡
    a.随机选择从库
        a.简单负载均衡
            type DBCluster struct {
                master *xorm.Engine
                slaves []*xorm.Engine
            }

            func NewDBCluster(masterDSN string, slaveDSNs []string) (*DBCluster, error) {
                master, err := xorm.NewEngine("mysql", masterDSN)
                if err != nil {
                    return nil, err
                }

                slaves := make([]*xorm.Engine, 0)
                for _, dsn := range slaveDSNs {
                    slave, err := xorm.NewEngine("mysql", dsn)
                    if err != nil {
                        return nil, err
                    }
                    slaves = append(slaves, slave)
                }

                return &DBCluster{
                    master: master,
                    slaves: slaves,
                }, nil
            }

            func (c *DBCluster) Master() *xorm.Engine {
                return c.master
            }

            func (c *DBCluster) Slave() *xorm.Engine {
                if len(c.slaves) == 0 {
                    return c.master
                }
                // 随机选择一个从库
                idx := rand.Intn(len(c.slaves))
                return c.slaves[idx]
            }

04.使用示例
    a.读写分离示例
        a.完整示例
            // 初始化集群
            cluster, _ := NewDBCluster(
                "user:pass@tcp(master:3306)/db",
                []string{
                    "user:pass@tcp(slave1:3306)/db",
                    "user:pass@tcp(slave2:3306)/db",
                },
            )

            // 写操作
            user := User{Name: "Alice"}
            cluster.Master().Insert(&user)

            // 读操作
            users := make([]User, 0)
            cluster.Slave().Find(&users)

            // 查询单条
            user2 := User{Id: 1}
            cluster.Slave().Get(&user2)

05.主从延迟
    a.处理延迟
        a.强制读主库
            // 写入后立即读取,使用主库
            cluster.Master().Insert(&user)

            // 立即读取,使用主库避免延迟
            user2 := User{Id: user.Id}
            cluster.Master().Get(&user2)
        b.延迟容忍
            // 对延迟不敏感的查询,使用从库
            users := make([]User, 0)
            cluster.Slave().Where("status = ?", 1).Find(&users)

06.健康检查
    a.从库健康检查
        a.检查可用性
            func (c *DBCluster) CheckSlaves() {
                for i, slave := range c.slaves {
                    err := slave.Ping()
                    if err != nil {
                        log.Printf("Slave %d is down: %v", i, err)
                        // 从列表中移除不可用的从库
                    }
                }
            }

            // 定期检查
            ticker := time.NewTicker(30 * time.Second)
            go func() {
                for range ticker.C {
                    cluster.CheckSlaves()
                }
            }()

7.5 事件系统

01.事件钩子
    a.Before钩子
        a.BeforeInsert
            func (u *User) BeforeInsert() {
                u.Created = time.Now()
                u.Updated = time.Now()
                log.Printf("准备插入用户: %s", u.Name)
            }
        b.BeforeUpdate
            func (u *User) BeforeUpdate() {
                u.Updated = time.Now()
                log.Printf("准备更新用户: %d", u.Id)
            }
        c.BeforeDelete
            func (u *User) BeforeDelete() {
                log.Printf("准备删除用户: %d", u.Id)
            }

02.After钩子
    a.AfterInsert
        a.插入后处理
            func (u *User) AfterInsert() {
                log.Printf("用户已创建: ID=%d, Name=%s", u.Id, u.Name)
                // 发送欢迎邮件
                // SendWelcomeEmail(u.Email)
            }
        b.AfterUpdate
            func (u *User) AfterUpdate() {
                log.Printf("用户已更新: %d", u.Id)
                // 清除缓存
                // ClearUserCache(u.Id)
            }
        c.AfterDelete
            func (u *User) AfterDelete() {
                log.Printf("用户已删除: %d", u.Id)
                // 清理关联数据
                // CleanupUserData(u.Id)
            }

03.AfterLoad钩子
    a.查询后处理
        a.数据转换
            func (u *User) AfterLoad() {
                // 查询后的数据处理
                u.Name = strings.ToUpper(u.Name)
            }

04.事件应用
    a.审计日志
        a.记录操作日志
            type User struct {
                Id      int64
                Name    string
                Email   string
                Created time.Time
                Updated time.Time
            }

            func (u *User) AfterInsert() {
                log := AuditLog{
                    TableName:  "user",
                    RecordId:   u.Id,
                    Action:     "INSERT",
                    OccurredAt: time.Now(),
                }
                engine.Insert(&log)
            }

            func (u *User) AfterUpdate() {
                log := AuditLog{
                    TableName:  "user",
                    RecordId:   u.Id,
                    Action:     "UPDATE",
                    OccurredAt: time.Now(),
                }
                engine.Insert(&log)
            }

05.数据验证
    a.插入前验证
        a.验证规则
            func (u *User) BeforeInsert() {
                if u.Name == "" {
                    log.Error("用户名不能为空")
                    // 注意:钩子方法���能返回error
                }

                if !strings.Contains(u.Email, "@") {
                    log.Error("邮箱格式不正确")
                }

                if u.Age < 0 || u.Age > 150 {
                    log.Error("年龄不合法")
                }
            }

06.注意事项
    a.钩子限制
        a.不能返回错误
            // ❌ 钩子方法不能返回error
            func (u *User) BeforeInsert() error {
                return errors.New("error")  // 不支持
            }

            // ✅ 只能记录日志
            func (u *User) BeforeInsert() {
                if u.Name == "" {
                    log.Error("用户名为空")
                }
            }
        b.执行顺序
            // Insert: BeforeInsert -> INSERT -> AfterInsert
            // Update: BeforeUpdate -> UPDATE -> AfterUpdate
            // Delete: BeforeDelete -> DELETE -> AfterDelete
            // Query: SELECT -> AfterLoad

7.6 最佳实践

01.模型设计
    a.字段规范
        a.标准模型
            type User struct {
                Id        int64     `xorm:"pk autoincr"`
                Name      string    `xorm:"varchar(100) notnull index"`
                Email     string    `xorm:"varchar(100) unique notnull"`
                Age       int       `xorm:"default 0 index"`
                Status    int       `xorm:"default 1 index"`
                Created   time.Time `xorm:"created"`
                Updated   time.Time `xorm:"updated"`
                DeletedAt time.Time `xorm:"deleted"`
            }
        b.命名规范
            // 1. 使用驼峰命名
            // 2. 主键使用Id
            // 3. 时间字段使用Created/Updated
            // 4. 软删除使用DeletedAt

02.查询优化
    a.优化建议
        a.使用索引
            // ✅ 在查询条件字段上添加索引
            type User struct {
                Email string `xorm:"unique"`  // 唯一索引
                Name  string `xorm:"index"`   // 普通索引
                Age   int    `xorm:"index"`   // 普通索引
            }
        b.避免SELECT *
            // ❌ 查询所有字段
            engine.Find(&users)

            // ✅ 只查询需要的字段
            engine.Cols("id", "name", "email").Find(&users)
        c.使用缓存
            // 启用查询缓存
            cacher := caches.NewLRUCacher(caches.NewMemoryStore(), 1000)
            engine.SetDefaultCacher(cacher)
        d.批量操作
            // ✅ 批量插入
            engine.Insert(&users)

            // ❌ 循环插入
            for _, user := range users {
                engine.Insert(&user)
            }

03.事务使用
    a.事务范围
        a.最小化事务
            // ✅ 事务范围尽可能小
            session := engine.NewSession()
            defer session.Close()

            session.Begin()
            session.Insert(&user)
            session.Insert(&order)
            session.Commit()

            // ❌ 事务范围过大
            session.Begin()
            // 大量业务逻辑
            // 网络请求
            // 文件操作
            session.Commit()

04.错误处理
    a.统一处理
        a.错误检查
            // ✅ 检查错误
            affected, err := engine.Insert(&user)
            if err != nil {
                log.Error("插入失败:", err)
                return err
            }
            if affected == 0 {
                log.Warn("没有插入任何记录")
            }

            // ❌ 忽略错���
            engine.Insert(&user)

05.连接管理
    a.连接池配置
        a.合理配置
            // 根据并发量调整
            engine.SetMaxIdleConns(10)
            engine.SetMaxOpenConns(100)
            engine.SetConnMaxLifetime(time.Hour)
        b.Session管理
            // ✅ 使用defer关闭
            session := engine.NewSession()
            defer session.Close()

            // ❌ 忘记关闭
            session := engine.NewSession()
            session.Insert(&user)

06.安全建议
    a.SQL注入防护
        a.参数绑定
            // ✅ 使用参数绑定
            engine.Where("name = ?", name).Find(&users)

            // ❌ 直接拼接SQL
            sql := fmt.Sprintf("SELECT * FROM user WHERE name = '%s'", name)
            engine.SQL(sql).Find(&users)
        b.输入验证
            // 验证用户输入
            func ValidateUser(user *User) error {
                if user.Name == "" {
                    return errors.New("用户名不能为空")
                }
                if !regexp.MustCompile(`^[a-zA-Z0-9_]+$`).MatchString(user.Name) {
                    return errors.New("用户名格式不正确")
                }
                if !strings.Contains(user.Email, "@") {
                    return errors.New("邮箱格式不正确")
                }
                return nil
            }