go语言web开发21 - beego框架之go orm使用06 - orm表关联查询

前面的文章了建了如下几张表:

  • 作者模型(Author):
  • 作者信息模型(AuthorInfo):AuthorInfo和Author表之间是一对一的关系(一个作者有一个单独的作者信息)
  • 文章模型(Article):Author和Article表之间是一对多的关系(一个作者可以发表多篇文章)
  • 标签模型(Tags):Article和Tags表之间是多对多的关系(一篇文章可以对应多个标签,一个标签也可以对应多篇文章)

上面的表里有一对一关联,一对多关联和多对多关联的表,前面文章里也介绍了orm的基本增删改查与原生sql的增删改查,今天介绍下表关联的增删改查,具体看下面示例。

 

一、一对一关联的相关操作

1.1、一对一表关联的插入操作

(1)、orm实现一对一关联的插入操作

func (c *OneToOneController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象与数据库连接
    o := orm.NewOrm()
    o.Using("default")


    // 一对一orm实现插入操作
    // 定义作者表的数据
    author := models.Author{AuthorName: "金庸巨著", Age: 48, Gender: "不详"}
    _, err := o.Insert(&author)        // 作者表插入数据
    if err == nil {       // 如果作者表插入没有报错,就插入关联的作者信息表数据
        author_info := models.AuthorInfo{Phone: "15011110000", ProvinceCity: "湖北·武汉", Addr: "xxx区xxx号xxx号楼xxx室", Author: &author}
        o.Insert(&author_info)
    }
}

 

(2)、原生sql实现一对一表关联插入数据

func (c *OneToOneController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象与数据库连接
    o := orm.NewOrm()
    o.Using("default")

    // 一对一原生sql实现插入
    // 先往作者表插入数据
    ret, err := o.Raw(`INSERT INTO author(author_name, age, gender) VALUE(?, ?, ?)`, "金庸新著1", 47, "不详").Exec()
    if err == nil {         // 作者表插入数据没问题获取插入数据的id
        author_id, _ := ret.LastInsertId()
        // 再往作者表关联的表插入数据
        ret, err := o.Raw(`INSERT INTO author_info(phone, province_city, addr, author_id) VALUE(?, ?, ?, ?)`, "15101107456", "湖北·宜昌", "xxx区xxx号xxx号楼xxx室", author_id).Exec()
        if err != nil {
            fmt.Println("insert data failed, err:", err)
        }
        fmt.Println(ret.LastInsertId())     // 打印插入数据的id
    }
}

 

1.2、一对一更新操作

func (c *OneToOneController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象与数据库连接
    o := orm.NewOrm()
    o.Using("default")


    //一、 一对一更新orm实现(只更新外键关联即可,其他的数据更新都属于单表更新了)
    author_id := 2
    // 根据查询条件直接执行更新操作
    num,err := o.QueryTable("author_info").Filter("author_id__exact", 11).Update(orm.Params{
        "author_id": author_id,
    })
    if err != nil {
        fmt.Println("update data failed, err:", err)
    }
    fmt.Println(num)



    //二、 一对一更新原生sql实现(只更新外键关联即刻,更新其他数据都属于单表操作了)
    ret, err := o.Raw(`update author_info set author_id=? where author_id=?`, 1, 2).Exec()
    if err != nil {
        fmt.Println("原生sql更新数据失败,err:",err)
    }
    fmt.Println(ret.LastInsertId())

}

 

1.3、一对一表关联删除操作

func (c *OneToOneController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象与数据库连接
    o := orm.NewOrm()
    o.Using("default")


    // 一、一对一实现删除数据orm实现
    // 根据查询条件删除,删除主表的数据后orm自动将从表的关联数据删除
    num, err := o.QueryTable("author").Filter("id__exact", 11).Delete()
    if err != nil {
        fmt.Println("delete data failed, err", err)
    }
    fmt.Println(num)


    // 二、一对一删除原生sql实现
    author_id := 10
    o.Raw(`DELETE FROM author WHERE id = ?`, author_id).Exec()
    o.Raw(`DELETE FROM author_info WHERE author_id = ?`, author_id).Exec()

 

1.4、一对一表关联查询操作

func (c *OneToOneController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象与数据库连接
    o := orm.NewOrm()
    o.Using("default")


    // 一对一查询orm实现
    // 一对一正向查询orm实现
    author_info := models.AuthorInfo{}
    author_info_id := 2
    // .RelatedSel():关联查询(前提条件:在有外键的表查询关联表)
    o.QueryTable("author_info").Filter("id__exact",author_info_id).RelatedSel().One(&author_info)
    fmt.Println(author_info)     // 作者信息表查询的数据
    fmt.Println(author_info.Author)      // 根据作者信息表的外键查询导的作者表数据



    // 一对一原生sql实现
    author_id := 1
    author := models.Author{}
    author_info := models.AuthorInfo{}
    o.Raw(`SELECT id, phone, province_city, addr from author_info WHERE author_id = ?`, author_id).QueryRow(&author_info)
    o.Raw(`SELECT id, author_name, age, gender from author WHERE id = ?`,author_id).QueryRow(&author)
    fmt.Println(author)       // 作者表数据
    fmt.Println(author_info)       // 作者信息表数据

 

二、表关系一对多相关操作

func (c *OneToManyController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象与连接数据库
    o := orm.NewOrm()
    o.Using("default")




    //一对多插入orm实现
    // 定义作者表数据
    author := models.Author{AuthorName: "金庸巨著", Age: 55, Gender: "不详"}
    o.Insert(&author)        // 插入作者表数据
    // 定义文章表数据,两条
    article := models.Article{ArticleTitle: "beego教程", Desc: "beego框架是xxxxxxxxxx", CreateTime: time.Now(), Author: &author}
    article1 := models.Article{ArticleTitle: "beego教程1", Desc: "beego1框架是xxxxxxxxxx", CreateTime: time.Now(), Author: &author}       // 一对多之间的关联通过 Author: &author字段实现
    o.Insert(&article)
    o.Insert(&article1)


    // 一对多插入原生sql实现
    nowTime := fmt.Sprintf("%02d-%02d-%02d\n", time.Now().Year(), time.Now().Month(), time.Now().Day())
    // 作者表插入数据
    ret, err := o.Raw(`INSERT INTO author(author_name, age, gender) VALUES(?, ?, ?)`, "唐家三少", 26, "").Exec()
    if err == nil {
        author_id, err := ret.LastInsertId()
        if err == nil {
            // 作者表插入数据没问题后获取作者表插入数据的id,然后网文章表插入数据
            o.Raw("INSERT INTO article(`article_title`, `desc`, `create_time`, `author_id`) VALUES(? , ?, ?, ?)", "斗罗大陆", "斗罗大陆是xxxxxxxxx", nowTime, author_id).Exec()
            o.Raw("INSERT INTO article(`article_title`, `desc`, `create_time`, `author_id`) VALUES(? , ?, ?, ?)", "斗罗大陆1", "斗罗大陆1是xxxxxxxxx", nowTime, author_id).Exec()
        }
    }




    // 一对多更新数据
    // orm更新实现
    o.QueryTable("article").Filter("author_id__exact", 2).Update(orm.Params{
        "author_id": 1,
    })

    // 原生sql实现
    ret, err := o.Raw(`update article set author_id=? where author_id=?`, 2, 1).Exec()
    if err != nil {
        fmt.Println("update one to many failed, err", err)
    }
    fmt.Println(ret.LastInsertId())
    fmt.Println(ret.RowsAffected())




    // 一对多删除
    // orm实现
    o.QueryTable("author").Filter("id__exact", 19).Delete()


    // 原生sql实现
    _, err := o.Raw(`DELETE FROM author WHERE id=?`, 20).Exec()
    if err == nil {
        o.Raw(`DELETE FROM article WHERE author_id=?`, 20).Exec()
    }



    // 一对多查询
    // orm查询一:根据文章id查作者
    var aid int32
    aid = 6
    ret_articles := models.Article{Id:aid}
    qs := o.QueryTable("article")
    qs.Filter("id__exact", aid).RelatedSel().One(&ret_articles)      // .RelatedSel():关联查询(前提条件:在有外键的表查询关联表)
    fmt.Println(ret_articles)    // 根据文章id查询的文章信息
    fmt.Println(ret_articles.Author)      // 文章关联的作者信息


    // 原生sql查询:根据文章id查作者
    article := models.Article{}
    author := models.Author{}
    o.Raw(`select * from article where id = ?`, 6).QueryRow(&article)
    authot_id := article.Author
    o.Raw(`select * from author where id = ?`, authot_id).QueryRow(&author)
    fmt.Println(article)
    fmt.Println(author)


    // 查询二:已知作者id,查询作者写过的文章
    orm实现
    orm_article := []models.Article{}
    o.QueryTable("article").Filter("author_id__exact",18).RelatedSel().All(&orm_article)
    fmt.Println(orm_article)
    for _, article := range orm_article {     // 循环获取文章的作者信息
        fmt.Println(article.Author)
    }


    // 原生sql实现
    article := []models.Article{}
    author := models.Author{}
    o.Raw(`select * from article where author_id = ?`, 18).QueryRows(&article)
    o.Raw(`select * from author where id = ?`, 18).QueryRow(&author)
    fmt.Println(article)
    fmt.Println(author)


    // 查询三:已知文章id,查询该文章的作者
    // orm实现:反向查询
    author := models.Author{}
    o.QueryTable("author").Filter("Article__Id",6).One(&author)
    fmt.Println(author)


    // 原生sql实现
    article := models.Article{}
    o.Raw(`select id,author_id from article where id=?`, 6).QueryRow(&article)
    author_id := article.Author
    author1 := models.Author{}
    o.Raw(`select * from author where id = ?`, author_id).QueryRow(&author1)
    fmt.Println(author1)

}

 

三、表关系:对多对操作

func (c *ManyToManyController) Get() {
    // 开启sql打印
    orm.Debug = true

    // 实例化orm对象和使用数据库
    o := orm.NewOrm()
    o.Using("default")




    // 一、多对多插入
    // 多对多orm插入方式一
    tags := models.Tags{TagName: "Beego", TagDesc: "Beego是go语言的web框架", CreateTime: time.Now()}
    o.Insert(&tags)       // 先往tags表里插入几条数据
    article := models.Article{Id: 2}
    m2m := o.QueryM2M(&article, "Tags")    // o.QueryM2M(要查询的表, 关联查询另外一张表的模型名称(字符串类型))
    m2m.Add(&tags)    // Add(&上面模型对应的表)


    // 多对多orm查询的方式二
    tags := models.Tags{TagName: "斗罗大陆小说", TagDesc: "斗罗大陆小说是唐家三少写的xxx", CreateTime: time.Now()}
    o.Insert(&tags)
    article := models.Article{Id: 5}
    m2m := o.QueryM2M(&tags, "Article")    // o.QueryM2M(要查询的表, 关联查询另外一张表的模型名称(字符串类型))
    m2m.Add(&article)    // Add(&上面模型对应的表)


    // 多对多插入原生sql实现
    nowTime := fmt.Sprintf("%02d-%02d-%02d\n", time.Now().Year(), time.Now().Month(), time.Now().Day())
    ret, err := o.Raw(`INSERT INTO tags(tag_name, tag_desc, create_time) VALUE(?, ?, ?)`, "python", "python是一门解释性编程语言,xxx", nowTime).Exec()
    if err == nil {
        ret1, err1 := o.Raw("INSERT INTO article(`article_title`, `desc`, `create_time`, `author_id`) VALUES(?, ?, ?, ?)", "python教程", "python教程是xxx", nowTime, 2).Exec()
        if err1 == nil {
            tags_id, get_tagsID_err := ret.LastInsertId()
            article_id, get_articleID_err := ret1.LastInsertId()
            if get_tagsID_err == nil && get_articleID_err == nil {
                _, err := o.Raw(`INSERT INTO article_tags(article_id, tags_id) VALUES(?, ?)`, article_id, tags_id).Exec()
                if err == nil {
                    fmt.Println("many to many insert failed, err:", err)
                }
            }
        }
    }




    // 多对多删除数据
    // 2.1、orm多对多删除之remove删除:删除指定的关联表数据,数据表里的数据不动
    article := models.Article{Id:2}
    tags := []models.Tags{{Id:1},{Id:2}}      // 多个删除时要用切片
    tags := models.Tags{Id:1}       // 删除关联的指定的数据
    m2m := o.QueryM2M(&article_many, "Tags")
    m2m.Remove(&tags)


    // 2.2、orm多对多删除之clear删除:删除所有关联的数据
    article := models.Article{Id:2}
    m2m := o.QueryM2M(&article_many, "Tags")
    m2m.Clear()


    // 2.3、原生sql多对多删除
    article := models.Article{}
    tags := models.Tags{}
    o.Raw(`SELECT id, article_title from article WHERE article_title = ?`, "python教程").QueryRow(&article)
    o.Raw(`select id, tag_name from tags WHERE tag_name = "python";`).QueryRow(&tags)
    article_id := article.Id
    tags_id := tags.Id
    _, err := o.Raw(`DELETE FROM article_tags WHERE article_id = ? and tags_id = ?`, article_id, tags_id).Exec()
    if err != nil {
        fmt.Println("many to many delete failed, err:", err)
    }




    // 三、Count:计数与、Exist:判断关联数据是否存在
    // 3.1、count:计数
    article := models.ArticleMany{Id:4}
    m2m := o.QueryM2M(&article, "Tags")
    num, err := m2m.Count()    // 获取关联的数据条数
    if err != nil {
        fmt.Println("QueryM2M Count Failed, err:", err)
    }
    fmt.Println(num)


    // 3.2、exist:判断是否存在
    article := models.Article{Id:3}
    tags := models.Tags{Id:1}
    m2m := o.QueryM2M(&article, "Tags")
    ret := m2m.Exist(&tags)
    fmt.Println(ret)      // 存在关联就返回true、不存在关联就返回false




    // 四、多对多更新数据
    // 4.1、orm实现多对多更新
    aid := 4
    tid := 1
    new_aid := 8
    new_tid := 3
    qs := o.QueryTable("article_tags")
    num, err := qs.Filter("article_id__exact", aid).Filter("tags_id__exact", tid).Update(orm.Params{
        "article_id": new_aid,
        "tags_id": new_tid,
    })
    if err != nil {
        fmt.Println("m2m update failed, err:", err)
    }
    fmt.Println(num)


    // 4.2、原生sql实现多对多更新
    o.Raw(`UPDATE article_tags SET article_id = ?,tags_id = ? WHERE article_id = ? AND tags_id = ?`, 5, 2, 6, 2).Exec()




    // 五、多对多查询
    // 5.1、orm实现:已知文章id,查询文章上绑定的tag信息
    aid := 2
    article := models.Article{}

                o.QueryTable("article").Filter("id__exact",aid).One(&article)
    fmt.Println(article)
    o.LoadRelated(&article, "Tags")
    for _, tags := range article.Tags {
        fmt.Println(tags)
    }


    // 5.2、已知tag的id,查询绑定tag的文章,从文章表查询
    tid := 2
    article := []models.Article{}
    qs := o.QueryTable("article")
    qs.Filter("Tags__tags__id__exact", tid).All(&article)      //Tags__tags__id:关系名__表名__字段名
    fmt.Println(article)


    // 5.3、已知文章的id,查询文章绑定的所有tag,从tags表查询, ***找不到该字段:article_many
    aid := 5
    tags := []models.Tags{}
    qs1 := o.QueryTable("tags")
    qs1.Filter("Article__article__id__exact", aid).All(&tags)
    fmt.Println(tags)

}

 

posted @ 2020-09-29 16:03  欧-阳  阅读(1023)  评论(0)    收藏  举报