xorm使用

定义关系模型

关系说明:(逻辑外键在子表上)
  • 教师表(子表)1:教师详细表(主表)1
  • 课程表(子表)N:教师表(主表)1
  • 课程表(主表)N:学生表(主表)N,需要成绩表(作为关系表)
结构体类型说明

时间使用time.Time
主键使用int64
分数使用decimal.Decimal

结构体tag说明

xorm:"index":增加索引
xorm:"created"xorm:"updated"xorm:"deleted" :自动生成时间
Id int64:此形式自动表示xorm:"pk autoincr"
xorm:"extends":应用于一个匿名成员结构体或者非匿名成员结构体之上,表示此结构体的所有成员也映射到数据库中,extends可加载无限级
-:这个Field将不进行字段映射
version:这个Field将会在insert时默认为1,每次更新自动加1
参考:http://gobook.io/read/github.com/go-xorm/manual-zh-CN/chapter-02/4.columns.html

//教师详细信息
type Detail struct {
    Id        int64
    Email     string
    Addr      string
    Tel       string
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//学生
type Student struct {
    Id        int64
    Name      string
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//教师
type Teacher struct {
    Id        int64
    Name      string
    DetailId  int64     `xorm:"index notnull"`
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//课程
type Course struct {
    Id        int64
    Name      string
    TeacherId int64     `xorm:"index notnull"`
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//成绩表
type Performance struct {
    Id        int64
    CourseId  int64 `xorm:"index notnull"`
    StudentId int64 `xorm:"index notnull"`
    Score     decimal.Decimal
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

查询

1对1查询、1对多查询
  • 教师表(子表)1:教师详细表(主表)1
//教师表
type Teacher struct {
    Id        int64
    Name      string
    DetailId  int64     `xorm:"index notnull"` //这里添加逻辑外键,不添加真实约束
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}
//教师详细表
type Detail struct {
    Id        int64
    Email     string
    Addr      string
    Tel       string
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

添加关联结构体

type TeacherDetail struct {
    Teacher `xorm:"extends"` //使用extends继承所有字段
    Detail  `xorm:"extends"` 
}

func (TeacherDetail) TableName() string {
    //指定使用该结构体对象 进行数据库查询时,使用的表名,这里返回子表名称
    return "teacher"
}

查询调用

    //1对1查询(1教师:1教师详情),子表:教师表,主表:详情表
    tcherDetails := make([]TeacherDetail, 0)
    engine.Join("LEFT", "detail", "teacher.detail_id=detail.id").Find(&tcherDetails)
    logrus.Infof("查询1对1(1教师:1教师详情):%v", tcherDetails)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.692951 [SQL] SELECT `teacher`.*, `detail`.* FROM `teacher` LEFT JOIN detail ON teacher.detail_id=detail.id
    INFO[0000] 查询1对1(1教师:1教师详情):[{{1 卡卡西 1 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {1 [email protected] 卡卡卡 卡卡卡卡卡 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}} {{2 凯 2 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 [email protected] 木叶村 11111111 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}}]
    */
  • 课程表(子表)N:教师表(主表)1
//课程
type Course struct {
    Id        int64
    Name      string
    TeacherId int64     `xorm:"index notnull"` //添加逻辑外键
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

添加关联结构体

type CourseTeacher struct {
    Course  `xorm:"extends"`
    Teacher `xorm:"extends"`
}

func (CourseTeacher) TableName() string {
    return "course" //返回子表名称
}

查询调用

    //1对多查询(1个老师:N个课程;1个课程:1个老师),子表:课程表,主表:教师表
    courseTchers := make([]CourseTeacher, 0) //声明数组
    engine.Join("LEFT", "teacher", "course.teacher_id=teacher.id").Find(&courseTchers)
    logrus.Infof("查询1对多(N课程:1老师):%v", courseTchers)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.695181 [SQL] SELECT * FROM `course` LEFT JOIN teacher ON course.teacher_id=teacher.id
    INFO[0000] 查询1对多(N课程:1老师):[{{1 疾风手里剑 1 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {1 卡卡西 1 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}} {{2 基本体术 2 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 凯 2 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}}]
    */
多对多查询
  • 课程表(主表)N:学生表(主表)N,需要成绩表(作为关系表)
//成绩表
type Performance struct {
    Id        int64
    CourseId  int64 `xorm:"index notnull"` //添加逻辑外键
    StudentId int64 `xorm:"index notnull"` //添加逻辑外键
    Score     decimal.Decimal
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

查询调用

    //多对多查询(N课程:N学生),子表、关系表:成绩表,主表:课程表、学生表
    performs := make([]Performance, 0)
    engine.Join("LEFT", "course", "performance.course_id=course.id").
        Join("left", "student", "performance.student_id=student.id").
        Find(&performs)
    logrus.Infof("查询多对多(N课程:N学生):%v", performs)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.697606 [SQL] SELECT * FROM `performance` LEFT JOIN course ON performance.course_id=course.id left JOIN student ON performance.student_id=student.id
    INFO[0000] 查询多对多(N课程:N学生):[{1 1 1 100 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 1 2 60 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {3 1 3 80 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}]
    */

完整示例如下:

package main

import (
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "github.com/go-xorm/xorm"
    "github.com/shopspring/decimal"
    "github.com/sirupsen/logrus"
    "time"
    "xorm.io/core"
)

//教师详细信息
type Detail struct {
    Id        int64
    Email     string
    Addr      string
    Tel       string
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//学生
type Student struct {
    Id        int64
    Name      string
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//教师
type Teacher struct {
    Id        int64
    Name      string
    DetailId  int64     `xorm:"index notnull"`
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//课程
type Course struct {
    Id        int64
    Name      string
    TeacherId int64     `xorm:"index not null"`
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

//成绩表
type Performance struct {
    Id        int64
    CourseId  int64 `xorm:"index notnull"`
    StudentId int64 `xorm:"index notnull"`
    Score     decimal.Decimal
    CreatedAt time.Time `xorm:"created"`
    UpdatedAt time.Time `xorm:"updated"`
    DeletedAt time.Time `xorm:"deleted"`
}

type TeacherDetail struct {
    Teacher `xorm:"extends"`
    Detail  `xorm:"extends"`
}

//func (TeacherDetail) TableName() string {
//  //指定使用该结构体对象 进行数据库查询时,使用的表名
//  return "teacher"
//}

type CourseTeacher struct {
    Course  `xorm:"extends"`
    Teacher `xorm:"extends"`
}

func (CourseTeacher) TableName() string {
    return "course"
}

func main() {
    engine, err := xorm.NewEngine("mysql", "root:root@tcp(192.168.99.100:3308)/demo?charset=utf8&parseTime=true&loc=Local")
    if err != nil {
        logrus.Panicf("数据库连接错误,%v", err)
    }

    //设置日志显示
    engine.ShowSQL(true)
    engine.SetLogLevel(core.LOG_DEBUG)

    //设置连接池
    engine.SetMaxOpenConns(3)
    engine.SetMaxIdleConns(1)
    engine.SetConnMaxLifetime(12 * time.Hour)

    // 设置缓存
    // cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
    // engine.SetDefaultCacher(cacher)

    //测试连接
    engine.Ping()

    //将结构体同步到数据库
    //推荐生产环境按照传统的flyway的处理方式,
    //将每个版本的sql幂等处理、编号、归档,升级时各局点存储升级记录、做sql文件md5校验,避免混乱。
    //而通过sync2方式编写sql升级管理流程,每次升级需要编写升级代码,显然通过sql的配置文件的形式更方便。
    err = engine.Sync2(new(Detail), new(Student), new(Teacher), new(Course), new(Performance))
    if err != nil {
        logrus.Panicf("同步到数据库失败,%v", err)
    }

    //插入基础数据
    detail1 := &Detail{Id: 1, Tel: "卡卡卡卡卡", Addr: "卡卡卡", Email: "[email protected]"}
    detail2 := &Detail{Id: 2, Tel: "11111111", Addr: "木叶村", Email: "[email protected]"}
    stu1 := &Student{Id: 1, Name: "佐助"}
    stu2 := &Student{Id: 2, Name: "鸣人"}
    stu3 := &Student{Id: 3, Name: "小樱"}
    stu4 := &Student{Id: 4, Name: "雏田"}
    tcher1 := &Teacher{Id: 1, Name: "卡卡西", DetailId: 1}
    tcher2 := &Teacher{Id: 2, Name: "凯", DetailId: 2}
    course1 := &Course{Name: "疾风手里剑", TeacherId: 1}
    course2 := &Course{Name: "基本体术", TeacherId: 2}
    perf1 := &Performance{CourseId: 1, StudentId: 1, Score: decimal.NewFromFloat(100)}
    perf2 := &Performance{CourseId: 1, StudentId: 2, Score: decimal.NewFromFloat(60)}
    perf3 := &Performance{CourseId: 1, StudentId: 3, Score: decimal.NewFromFloat(80)}

    engine.Insert(detail1, detail2, stu1, stu2, stu3, stu4, tcher1, tcher2, course1, course2, perf1, perf2, perf3)

    //单表,单条查询, 值存入传入的对象中
    theOne := &Student{Id: 1}
    theOther := &Student{}
    _, _ = engine.Get(theOne)
    _, _ = engine.Id(1).Get(theOther)
    _, _ = engine.Where("id=?", 1).Get(theOther)

    //软删除
    _, _ = engine.Delete(&Student{Name: "雏田"})

    //单表,多条查询,值存入传入的对象中
    //返回数组
    stuArr1 := make([]Student, 0) //make声明slice
    _ = []Student{}               //字面量声明slice
    engine.Find(&stuArr1)
    logrus.Infof("查询学生结构体数组:%v", stuArr1)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.689451 [SQL] SELECT `id`, `name`, `created_at`, `updated_at` FROM `student`
    INFO[0000] 查询学生结构体数组:[{1 佐助 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 鸣人 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {3 小樱 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}]
    */

    //返回map
    stuMap1 := make(map[int64]Student) //make声明Map
    _ = map[int64]Student{}            //字面量声明Map
    engine.Find(&stuMap1)
    logrus.Infof("查询学生map:%v", stuMap1)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.691631 [SQL] SELECT `id`, `name`, `created_at`, `updated_at` FROM `student`
    INFO[0000] 查询学生map:map[1:{1 佐助 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} 2:{2 鸣人 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} 3:{3 小樱 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}]
    */

    //1对1查询(1教师:1教师详情),子表:教师表,主表:详情表
    tcherDetails := make([]TeacherDetail, 0)
    engine.
                Table("teacher").   //使用Table指定时,可不用编写结构体的TableName方法
        //Cols("teacher.*", "detail.*").
        //Select("teacher.*,detail.*").
        Join("LEFT", "detail", "teacher.detail_id=detail.id").Find(&tcherDetails)
    logrus.Infof("查询1对1(1教师:1教师详情):%v", tcherDetails)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.692951 [SQL] SELECT `teacher`.*, `detail`.* FROM `teacher` LEFT JOIN detail ON teacher.detail_id=detail.id
    INFO[0000] 查询1对1(1教师:1教师详情):[{{1 卡卡西 1 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {1 [email protected] 卡卡卡 卡卡卡卡卡 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}} {{2 凯 2 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 [email protected] 木叶村 11111111 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}}]
    */

    //1对多查询(1个老师:N个课程;1个课程:1个老师),子表:课程表,主表:教师表
    courseTchers := make([]CourseTeacher, 0) //声明数组
    engine.Join("LEFT", "teacher", "course.teacher_id=teacher.id").Find(&courseTchers)
    logrus.Infof("查询1对多(N课程:1老师):%v", courseTchers)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.695181 [SQL] SELECT * FROM `course` LEFT JOIN teacher ON course.teacher_id=teacher.id
    INFO[0000] 查询1对多(N课程:1老师):[{{1 疾风手里剑 1 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {1 卡卡西 1 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}} {{2 基本体术 2 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 凯 2 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}}]
    */

    //多对多查询(N课程:N学生),子表、关系表:成绩表,主表:课程表、学生表
    performs := make([]Performance, 0)
    engine.Join("LEFT", "course", "performance.course_id=course.id").
        Join("left", "student", "performance.student_id=student.id").
        Find(&performs)
    logrus.Infof("查询多对多(N课程:N学生):%v", performs)
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.697606 [SQL] SELECT * FROM `performance` LEFT JOIN course ON performance.course_id=course.id left JOIN student ON performance.student_id=student.id
    INFO[0000] 查询多对多(N课程:N学生):[{1 1 1 100 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {2 1 2 60 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST} {3 1 3 80 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}]
    */

    //不定义自己的集合,使用rows的封装类型返回
    newStu := new(Student)
    rows, err := engine.Rows(newStu)
    if err != nil {
    }
    defer rows.Close()
    for rows.Next() {
        _ = rows.Scan(newStu)
        logrus.Infof("newStu:%v", newStu)
    }
    /* 执行结果
    [xorm] [info]  2019/08/14 16:02:58.700549 [SQL] SELECT `id`, `name`, `created_at`, `updated_at` FROM `student`

    INFO[0000] newStu:&{1 佐助 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}
    INFO[0000] newStu:&{2 鸣人 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}
    INFO[0000] newStu:&{3 小樱 2019-08-14 14:24:56 +0800 CST 2019-08-14 14:24:56 +0800 CST}
    */

    //执行sql
    sql1 := "select * from student where id = ?"
    queryRet, err := engine.Query(sql1, 1)
    logrus.Infof("使用sql查询结果:%v", queryRet)
    /* 执行结果
    [xorm] [info]  2019/08/14 17:52:00.199751 [SQL] select * from student where id = ? []interface {}{1}
    INFO[0000] 使用sql查询结果:[map[created_at:[50 48 49 57 45 48 56 45 49 52 84 49 54 58 50 51 58 52 51 43 48 56 58 48 48] deleted_at:[] id:[49] name:[228 189 144 229 138 169] updated_at:[50 48 49 57 45 48 56 45 49 52 84 49 54 58 50 51 58 52 51 43 48 56 58 48 48]]]
    */

    sql2 := "insert into student (name,created_at,updated_at) values (?,now(),now())"
    ret, err := engine.Exec(sql2, "日向宁次")
    lastInsertId, _ := ret.LastInsertId()
    effectedRows, _ := ret.RowsAffected()
    logrus.Infof("执行sql命令结果,插入id:%v,影响行数:%v",
        lastInsertId, effectedRows)
    /* 执行结果
    [xorm] [info]  2019/08/14 17:52:00.200798 [SQL] insert into student (name) values (?) []interface {}{"日向宁次"}
    INFO[0000] 执行sql命令结果,插入id:8,影响行数:1
    */

    //事务
    txExample(engine)

    //事件
    before := func(bean interface{}) {
        fmt.Println("before", bean)
    }
    after := func(bean interface{}) {
        fmt.Println("after", bean)
    }
    engine.Before(before).After(after).Get(new(Student))
    /* 执行结果
    before &{0  0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC}
    after &{1 佐助 2019-08-14 16:23:43 +0800 CST 2019-08-14 16:23:43 +0800 CST 0001-01-01 00:00:00 +0000 UTC}
     */

}

func txExample(engine *xorm.Engine) {
    session := engine.NewSession()
    defer session.Close()

    //插入 教师详情
    detail := &Detail{
        Email: "[email protected]",
        Addr:  "木叶村",
        Tel:   "999",
    }

    _, err := session.Insert(detail) //insert后会更新 detail变量中的相关字段,id、createdAt、updatedAt等
    if err != nil {
        session.Rollback() //插入失败回滚
        return
    }

    //插入 教师
    tcher := &Teacher{
        Name:     "自来也",
        DetailId: detail.Id,
    }
    _, err = session.Insert(tcher)
    if err != nil {
        session.Rollback()
        return
    }
    err = session.Commit()
    if err != nil {
        return
    }
}

你可能感兴趣的:(xorm使用)