GoFrame ORM use practice sharing

Get into the habit of writing together! This is the third day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

foreword

This month, I will continue to update Go language related articles, especially GoFrame. Interested students can follow me and go together.

At the same time, I will summarize: "China-Taiwan Development Practice", "Private Deployment Practice", "In-depth understanding of goroutine and use practice", "How to reflect the value of GO language in the development process".

Determined to precipitate some high-quality content.

Today, this article GoFrame ORMshares the relevant knowledge points that I think are valuable, possible pitfalls, and better practices in the process of using it.

Value Types and Pointer Types

When I first learned go, I was entangled with value types and pointer types. Later, in the process of using it, I found that there is no need to entangle.

The advantage of the pointer type is that it saves memory space. Multiple variables point to the same memory address, and each one is prosperous. One modification can be modified everywhere.

The value type can be simply understood as: to avoid this problem of modifying one place and modifying everywhere, in some scenarios, we can't simply consider performance, and we can't just consider it 复用.

We are also encouraged to use pointer types in GoFrame, for example:

ScanConvert query results to structobjects using

ScanSupports converting the query result into an structobject. The query result should be a specific record, and the pointerparameter should be structthe pointer address ( *structor **struct) of the object. The usage is for example:

type User struct {
    Id         int
    Passport   string
    Password   string
    NickName   string
    CreateTime *gtime.Time
}
user := User{}
g.Model("user").Where("id", 1).Scan(&user)
复制代码

or

var user = User{}
g.Model("user").Where("id", 1).Scan(&user)
复制代码

The first two ways are to pre-initialize the object (allocate memory in advance)

The recommended method is as follows, this method will only perform initialization and memory allocation when the data is queried:

var user *User
g.Model("user").Where("id", 1).Scan(&user)
复制代码

Pay attention to the difference in usage, especially the difference in the type of parameters passed (the parameter type passed in the first two ways is *User, the parameter type passed here is actually **User).

insert data

InsertIgnore

这个函数需要重点和大家说一下,因为我之前有Laravel的使用经验,Laravel中的InsertIgnore是配合唯一索引使用,意思是如果存在唯一主键或者唯一索引就忽略掉,不重复插入。

在GoFrame中是相反的:

GoFrame中默认的insert函数,就会根据唯一索引(或主键)执行,如果有存在的数据返回失败,不重复插入。

而GoFrame中的InsertIgnore是忽略错误继续插入,而不是存在就不插入。

大家在使用中要注意。

灵活执行SQL

我们要拼接自定义的sql参数怎么办法呢?

gdb.Raw()

示例如下:

OnDuplicate(g.Map{
    "nickname": gdb.Raw("CONCAT('name_', VALUES(`nickname`))"),
})
复制代码

gdb.Raw() 中的参数将作为sql执行的语句,不会自动转换成字符串类型,也不会作为预处理参数。

示例如下:

// INSERT INTO `user`(`id`,`passport`,`password`,`nickname`,`create_time`) VALUES(id+2,'80','123456','wzy',now())
g.Model("user").Data(g.Map{
	"id":          gdb.Raw("id+2"),
	"passport":    "80",
	"password":    "123456",
	"nickname":    "wzy",
	"create_time": gdb.Raw("now()"),
}).Insert()
复制代码

链式安全

我们首先要有这个概念:什么是链式安全?

其实很简单:链式安全就是操作model模型时不会改变当前model对象,模型属性修改/条件叠加需要使用赋值来操作。

链式非安全或者非链式安全就是:操作model模型时会改变当前model对象的属性。

在GoFrame开发过程中,强烈建议使用gf gen dao生成的model和dao文件!!!

通过gf gen dao生成的model和dao文件默认是链式安全的。

举例如下:

func NewGomeStockDao() *GomeStockDao {
   return &GomeStockDao{
      M:     g.DB("default").Model("gome_stock").Safe(), //注意看这里
      DB:    g.DB("default"),
      Table: "gome_stock",
      Columns: gomeStockColumns{
         Id:            "id",
         MchWhseCode:   "mch_whse_code",
         MchWhseName:   "mch_whse_name",
         IsNationWide:  "is_nation_wide",
         Status:        "status",
         LastUpateTime: "last_upate_time",
      },
   }
}
复制代码

链式安全时我们如何叠加条件改变呢?

答案就是:通过赋值。

链式安全时通过 m = m.xxx 方式赋值实现链式调用

举例如下:

m := user.Where("status IN(?)", g.Slice{1,2,3})
if vip {
    // 查询条件通过赋值叠加
    m = m.And("money>=?", 1000000)
} else {
    // 查询条件通过赋值叠加
    m = m.And("money<?",  1000000)
}
//  vip: SELECT * FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT * FROM user WHERE status IN(1,2,3) AND money < 1000000
r, err := m.All()
//  vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money >= 1000000
// !vip: SELECT COUNT(1) FROM user WHERE status IN(1,2,3) AND money < 1000000
n, err := m.Count()
复制代码

总结

碰到好的东西就忍不住分享,我现在可以说是Go语言的忠实拥趸。

对GO感兴趣的朋友可以查看我之前写的文章,了解一下Go的魅力:

Go语言为什么值得学习?

我的PHP转Go之旅

回顾一下我的Go学习之旅

非常适合PHP和Java转Go学习的框架:GoFrame

欢迎大家关注我的Go语言学习专栏,我会持续更新在Go学习和使用过程中的干货分享。

Go语言学习专栏

最后

Thank you for reading, and welcome everyone: like, favorite,coin(focus on)! ! !

8e95dac1fd0b2b1ff51c08757667c47a.gif

Guess you like

Origin juejin.im/post/7082278651681013773