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) }