beego orm使用

dz45693發表於2020-12-14

初始化

建立新beego專案

bee new test

在main.go中開始測試

模型關係

# 外來鍵始終在子表上

#一個使用者對應一個簡介;一個簡介對應一個使用者;
one2one:User(子表) -> Profile(主表);one2one:Profile -> User 

#一個郵件對應一個使用者;一個使用者有多個郵件;
one2many:Post(子表) -> User(主表);many2one:User -> Post 

#一個郵件對應多個標籤;一個標籤對應多個郵件;
many2many:Post(子表) -> Tag(主表);many2many:Tag -> Post 

新建4個結構體

使用標籤`orm:"column(id)`對屬性進行標註,用於解析。
標註邏輯外來鍵,自動建表時不會生成外來鍵。
`orm:"rel(one)"` 表示one2one
`orm:"rel(fk)"`  表示one2many
`orm:"rel(m2m)"` 表示many2many
`orm:"reverse(one)"` `orm:"reverse(one)"`  標註反向關係

 

type User struct {
⇥   Id      int      `orm:"column(id);auto" description:"id"`
⇥   Name    string   `orm:"column(name)" description:"name"`
⇥   Profile *Profile `orm:"rel(one)"` // OneToOne relation
⇥   //Posts   []*Post  `orm:"reverse(many)"`  //one2many情況下,不要寫reverse
}

type Profile struct {
⇥   Id  int   `orm:"column(id);auto" description:"id"`
⇥   Age int16 `orm:"column(age)" description:"age"`
⇥   //User *User `orm:"reverse(one)"` // Reverse relationship (optional)
}

type Post struct {
⇥   Id    int    `orm:"column(id);auto" description:"id"`
⇥   Title string `orm:"column(title)" description:"title"`
⇥   User  *User  `orm:"rel(fk)"`  // OneToMany relation
⇥   Tags  []*Tag `orm:"rel(m2m)"` // m2m relation
}

type Tag struct {
⇥   Id   int    `orm:"column(id);auto" description:"id"`
⇥   Name string `orm:"column(name)" description:"name"`
⇥   Posts []*Post `orm:"reverse(many)"`
}

初始化操作

//ormer
var O orm.Ormer

func init() {
⇥   //註冊驅動
⇥   orm.RegisterDriver("mysql", orm.DRMySQL)
⇥   //註冊預設資料庫
⇥   orm.RegisterDataBase("default", "mysql", "root:root@tcp(192.168.99.100:3308)/test?charset=utf8")
⇥   //註冊model
⇥   orm.RegisterModel(new(User), new(Profile), new(Post), new(Tag))
⇥   //自動建表
⇥   orm.RunSyncdb("default", false, true)
⇥   //初始化ormer
⇥   O = orm.NewOrm()
⇥   //初始化資料
⇥   datainit()

}

生成的database資訊

執行之前,需要建立資料庫test,並配置資料庫資訊,字元編碼全部設定為utf8

執行:註冊model,自動建表 即可得到如下資訊。

 

mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| post           |
| post_tags      |
| profile        |
| tag            |
| user           |
+----------------+
5 rows in set (0.00 sec)

mysql> desc post;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| title   | varchar(255) | NO   |     |         |                |
| user_id | int(11)      | NO   |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> desc post_tags;
+---------+------------+------+-----+---------+----------------+
| Field   | Type       | Null | Key | Default | Extra          |
+---------+------------+------+-----+---------+----------------+
| id      | bigint(20) | NO   | PRI | NULL    | auto_increment |
| post_id | int(11)    | NO   |     | NULL    |                |
| tag_id  | int(11)    | NO   |     | NULL    |                |
+---------+------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> desc profile;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| age   | smallint(6) | NO   |     | 0       |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> desc tag;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | int(11)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255) | NO   |     |         |                |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> desc user;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     |         |                |
| profile_id | int(11)      | NO   | UNI | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

database生成規則

1.新增rel(one)、rel(fk)的屬性會生成 表名_id的欄位,rel(one)時生成欄位key為unique

type User struct {
    Profile *Profile `orm:"rel(one)"`
}

type Profile struct {
    User *User `orm:"reverse(one)"`  //可以省略
}
---->
mysql> desc user;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255) | NO   |     |         |                |
| profile_id | int(11)      | NO   | UNI | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

2.rel(m2m)、reverse(many)這一對欄位 會生成關係對應表 子表_主表s 主鍵自增

type Post struct {
    Tags  []*Tag `orm:"rel(m2m)"` // m2m relation
}

type Tag struct {
    Posts []*Post `orm:"reverse(many)"`
}
---->
mysql> desc post_tags;
+---------+------------+------+-----+---------+----------------+
| Field   | Type       | Null | Key | Default | Extra          |
+---------+------------+------+-----+---------+----------------+
| id      | bigint(20) | NO   | PRI | NULL    | auto_increment |
| post_id | int(11)    | NO   |     | NULL    |                |
| tag_id  | int(11)    | NO   |     | NULL    |                |
+---------+------------+------+-----+---------+----------------+

初始化資料

func datainit() {
⇥   //rel  : 自動生成外來鍵為 表名_id
⇥   sql1 := "insert into user (name,profile_id) values ('ming',1),('hua',2),('qiang',3);"
⇥   sql2 := "insert into profile (age) values (16),(14),(15);"
⇥   sql3 := "insert into tag (name) values ('offical'),('beta'),('dev');"
⇥   sql4 := "insert into post (title,user_id) values ('paper1',1),('paper2',1),('paper3',2),('paper4',3),('paper5',3);"
⇥   // m2m 生成的 表名:子表_主表s  主鍵自增
⇥   sql5 := "insert into post_tags (tag_id, post_id) values (1,1),(1,3),(2,2),(3,3),(2,4),(3,4),(3,5); "

    //使用Raw().Exec()執行sql
⇥   O.Raw(sql1).Exec()
⇥   O.Raw(sql2).Exec()
⇥   O.Raw(sql3).Exec()
⇥   O.Raw(sql4).Exec()
⇥   O.Raw(sql5).Exec()
}

查詢

one2one查詢

func one2one() {
⇥   //one to one :主表Profile 子表User [常用方式:使用級聯查詢全部資料]
⇥   fmt.Println("one2one-------------------------------")
⇥   //1.通過已知的 子表User資料,查詢主表Profile資料
⇥   user := &User{Id: 1}
⇥   O.Read(user) //查詢子表
⇥   if user.Profile != nil {
⇥   ⇥   O.Read(user.Profile)
⇥   }
⇥   fmt.Println("1.二次查詢 user now:", user)
⇥   fmt.Println("1.二次查詢 profile now:", user.Profile)
⇥   fmt.Println("-------------------------------")
⇥   //2.級聯查詢
⇥   user = &User{}
⇥   O.QueryTable("user").Filter("Id", 1).RelatedSel().One(user)
⇥   fmt.Println("2.級聯查詢 user:", user)
⇥   fmt.Println("2.級聯查詢 profile:", user.Profile)
⇥   fmt.Println("-------------------------------")
⇥   //3.reverse查詢 通過子表條件 查詢主表 ,此時並沒有獲取另一個表的資料
⇥   profile := Profile{}
⇥   O.QueryTable("profile").Filter("User__Id", 1).One(&profile)
⇥   fmt.Println("3.reserve 查詢 profile:", profile, "條件 user id:1")

⇥   profiles := []*Profile{}
⇥   O.QueryTable("profile").Filter("User__Name", "ming").One(&profiles)
⇥   for _, a := range profiles {
⇥   ⇥   fmt.Println("3.reserve 查詢 profile:", a, "條件 user name:ming")
⇥   }
⇥   fmt.Println("-------------------------------")
}

one2many查詢

func one2many() {
⇥   //one to many : 主表User 子表Post [常用方式:使用級聯查詢全部資料]
⇥   fmt.Println("one2many-------------------------------")
⇥   //1.級聯查詢
⇥   var posts []*Post
⇥   O.QueryTable("post").Filter("User__Id", 1).RelatedSel().All(&posts)
⇥   for _, v := range posts {
⇥   ⇥   fmt.Println("1.級聯查詢 post:", v)
⇥   ⇥   fmt.Println("1.級聯查詢 post.user.name:", v.User.Name)
⇥   }
⇥   fmt.Println("-------------------------------")
⇥   //2.reverse 查詢
⇥   var user User
⇥   err := O.QueryTable("user").Filter("Post__Title", "paper1").Limit(1).One(&user)
⇥   if err == nil {
⇥   ⇥   fmt.Println("2.reverse 查詢 user:", user)
⇥   } else {
⇥   ⇥   fmt.Println("err:", err)
⇥   }
⇥   fmt.Println("-------------------------------")

}

many2many查詢

func many2many() {
⇥   //many to many : 主表 Tag 子表Post
⇥   //1.reverse 查詢
⇥   fmt.Println("many2many-------------------------------")
⇥   var posts []*Post
⇥   O.QueryTable("post").Filter("Tags__Tag__Name", "offical").All(&posts)
⇥   for _, v := range posts {
⇥   ⇥   fmt.Println("1.reverse 查詢 post:", v)
⇥   }
⇥   fmt.Println("-------------------------------")

⇥   //reverse 查詢
⇥   var tags []*Tag
⇥   O.QueryTable("tag").Filter("Posts__Post__Title", "paper1").All(&tags)
⇥   for _, x := range tags {
⇥   ⇥   fmt.Println("2.reverse 查詢 tag:", x)
⇥   }
⇥   fmt.Println("-------------------------------")
⇥   //3.級聯查詢
⇥   //可以建立post_tags表的結構體MapPostTag,包含Post、Tag
⇥   //使用O.QueryTable("post_tags").RelatedSel().All(&MapPostTag)進行查詢

}

比較

我們常用的left join 查詢全部資料的兩種方式:

var entry Entry
O.QueryTable("子表").RelatedSel().All(&entry)


var maps []orm.Params
sql:="xxx;"
O.Raw(sql).Values(&maps)

通過如下程式碼進行返回比較響應json

//定義controller
type UserController struct {
⇥   beego.Controller
}

//定義urlmap到具體方法
func (c *UserController) URLMapping() {
⇥   c.Mapping("GetAll", c.GetAll)
}

func main() {
⇥   //註冊路由
⇥   beego.Router("/user", &UserController{}, "get:GetAll")
⇥   //啟動
⇥   beego.Run()
}

/*
//使用relatedsel自動級聯查詢
func (c *UserController) GetAll() {
⇥   var users []*User
⇥   O.QueryTable("user").RelatedSel().All(&users)
⇥   c.Data["json"] = users
⇥   c.ServeJSON()
}
*/

//使用原生sql進行查詢
func (c *UserController) GetAll() {
⇥   var maps []orm.Params
⇥   sql := `
⇥   ⇥   select * from user t1
⇥   ⇥   left join profile t2 on t1.profile_id=t2.id
⇥   `
⇥   O.Raw(sql).Values(&maps)
⇥   c.Data["json"] = maps
⇥   c.ServeJSON()
}


使用relatedsel自動級聯查詢 json:

[
  {
    "Id": 1,
    "Name": "ming",
    "Profile": {
      "Id": 1,
      "Age": 16
    }
  },
  {
    "Id": 2,
    "Name": "hua",
    "Profile": {
      "Id": 2,
      "Age": 14
    }
  },
  {
    "Id": 3,
    "Name": "qiang",
    "Profile": {
      "Id": 3,
      "Age": 15
    }
  }
]

使用原生sql進行查詢 json:

[
  {
    "age": "16",
    "id": "1",
    "name": "ming",
    "profile_id": "1"
  },
  {
    "age": "14",
    "id": "2",
    "name": "hua",
    "profile_id": "2"
  },
  {
    "age": "15",
    "id": "3",
    "name": "qiang",
    "profile_id": "3"
  }
]

load related查詢

func loadRelatedField() {
⇥   //適用於所有關係模型 one2one one2m m2m
⇥   fmt.Println("one2one:loadRelated---------------------")
⇥   user := User{Id: 1}
⇥   if err := O.Read(&user); err == nil {
⇥   ⇥   O.LoadRelated(&user, "Profile") //引數中寫入需要關聯的欄位即可
⇥   ⇥   fmt.Println("user:", user)
⇥   ⇥   fmt.Println("user.profile:", user.Profile)
⇥   }

⇥   post := Post{Id: 1}
⇥   if err := O.Read(&post); err == nil {
⇥   ⇥   O.LoadRelated(&post, "Tags")
⇥   ⇥   for _, v := range post.Tags {
⇥   ⇥   ⇥   fmt.Println("tag:", v)
⇥   ⇥   }
⇥   }

⇥   tag := Tag{Id: 1}
⇥   if err := O.Read(&tag); err == nil {
⇥   ⇥   O.LoadRelated(&tag, "Posts")
⇥   ⇥   for _, v := range tag.Posts {
⇥   ⇥   ⇥   fmt.Println("post:", v)
⇥   ⇥   }
⇥   }

}

插入

單表插入

⇥   //單表插入
⇥   fmt.Println("單表插入-------------")
⇥   profile:=Profile{Age:18}
⇥   id,err:=O.Insert(&profile)
⇥   fmt.Println("返回插入的id:",id)

one2one one2many插入

⇥   //one2one插入
⇥   err := O.Begin() //開啟事物
⇥   //插入主表
⇥   profile := Profile{Age: 19}
⇥   id, err := O.Insert(&profile)
⇥   if err != nil {
⇥   ⇥   O.Rollback()
⇥   } else {
⇥   ⇥   fmt.Println("success insert profile")
⇥   }
⇥   //插入子表
⇥   user := User{Name: "kakaxi", Profile: &Profile{Id: int(id)}}
⇥   _, err = O.Insert(&user)
⇥   if err != nil {
⇥   ⇥   O.Rollback()
⇥   } else {
⇥   ⇥   fmt.Println("success insert user")
⇥   }
⇥   err = O.Commit()

m2m插入

    //m2m
    //比如知道一個郵件物件post,一個標記物件tag,插入他們的對應關係
    O.Begin()
    //step1:插入post,獲取m2m物件
    user := User{Id: 1}
    O.Read(&user)                                    //讀取user
    post := Post{Title: "kakaxi開啟寫輪眼了", User: &user} //拼接post
    id, err := O.Insert(&post)                       //插入post
    if err != nil {
        O.Rollback()
        return err
    } else {
        fmt.Println("insert post success")
    }
    post = Post{Id: int(id)}
    m2m := O.QueryM2M(&post, "Tags") //建立m2m物件,Tags為關聯屬性
    //step2:插入tag
    tag := Tag{Name: "娛樂"}
    _, err = O.Insert(&tag)
    if err != nil {
        O.Rollback()
        return err
    } else {
        fmt.Println("insert tag success")
    }
    //step3:插入關係表
    num, err := m2m.Add(&tag)
    if err != nil {
        O.Rollback()
        return err
    } else {
        fmt.Println("insert post_tags success,added nums:", num)
    }
    O.Commit()
    return nil

更新

單表更新

o := orm.NewOrm()
user := User{Id: 1}
if o.Read(&user) == nil {
    user.Name = "MyName"
    if num, err := o.Update(&user); err == nil {
        fmt.Println(num)
    }
}

// Only update Name
o.Update(&user, "Name")
// Update multiple fields
// o.Update(&user, "Field1", "Field2", ...)

更新

。。。我已經不想學更新了,直接用Raw(sql).Exec()執行吧

刪除

單表刪除

o := orm.NewOrm()
if num, err := o.Delete(&User{Id: 1}); err == nil {
    fmt.Println(num)
}

 

相關文章