add DTO feature for package gdb

This commit is contained in:
John Guo
2021-12-15 00:01:59 +08:00
parent 36e05561cc
commit 19c9f0a488
3 changed files with 163 additions and 8 deletions

View File

@ -60,6 +60,7 @@ const (
OrmTagForWith = "with"
OrmTagForWithWhere = "where"
OrmTagForWithOrder = "order"
OrmTagForDto = "dto"
)
var (
@ -70,9 +71,25 @@ var (
structTagPriority = append([]string{OrmTagForStruct}, gconv.StructTagPriority...)
)
// isForDaoModel checks and returns whether given type is for dao model.
func isForDaoModel(t reflect.Type) bool {
return gstr.HasSuffix(t.String(), modelForDaoSuffix)
// isDtoStruct checks and returns whether given type is a DTO struct.
func isDtoStruct(object interface{}) bool {
// It checks by struct name like "XxxForDao", to be compatible with old version.
// TODO remove this compatible codes in future.
reflectType := reflect.TypeOf(object)
if gstr.HasSuffix(reflectType.String(), modelForDaoSuffix) {
return true
}
// It checks by struct meta for DTO struct in version.
if ormTag := gmeta.Get(object, OrmTagForStruct); !ormTag.IsEmpty() {
match, _ := gregex.MatchString(
fmt.Sprintf(`%s\s*:\s*([^,]+)`, OrmTagForDto),
ormTag.String(),
)
if len(match) > 1 {
return gconv.Bool(match[1])
}
}
return false
}
// getTableNameFromOrmTag retrieves and returns the table name from struct object.
@ -424,7 +441,7 @@ func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newAr
case reflect.Struct:
// If the `where` parameter is defined like `xxxForDao`, it then adds `OmitNil` option for this condition,
// which will filter all nil parameters in `where`.
if isForDaoModel(reflect.TypeOf(in.Where)) {
if isDtoStruct(in.Where) {
in.OmitNil = true
}
// If `where` struct implements iIterator interface,

View File

@ -73,10 +73,10 @@ func (m *Model) Data(data ...interface{}) *Model {
switch reflectInfo.OriginKind {
case reflect.Slice, reflect.Array:
if reflectInfo.OriginValue.Len() > 0 {
// If the `data` parameter is defined like `xxxForDao`,
// If the `data` parameter is a DTO struct,
// it then adds `OmitNilData` option for this condition,
// which will filter all nil parameters in `data`.
if isForDaoModel(reflectInfo.OriginValue.Index(0).Elem().Type()) {
if isDtoStruct(reflectInfo.OriginValue.Index(0).Interface()) {
model = model.OmitNilData()
model.option |= optionOmitNilDataInternal
}
@ -88,10 +88,10 @@ func (m *Model) Data(data ...interface{}) *Model {
model.data = list
case reflect.Struct:
// If the `data` parameter is defined like `xxxForDao`,
// If the `data` parameter is a DTO struct,
// it then adds `OmitNilData` option for this condition,
// which will filter all nil parameters in `data`.
if isForDaoModel(reflect.TypeOf(value)) {
if isDtoStruct(value) {
model = model.OmitNilData()
}
if v, ok := data[0].(iInterfaces); ok {

View File

@ -13,6 +13,144 @@ import (
"github.com/gogf/gf/v2/test/gtest"
)
func Test_Model_Insert_Data_DTO(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"dto:true"`
Id interface{}
Passport interface{}
Password interface{}
Nickname interface{}
CreateTime interface{}
}
data := User{
Id: 1,
Passport: "user_1",
Password: "pass_1",
}
result, err := db.Model(table).Data(data).Insert()
t.AssertNil(err)
n, _ := result.LastInsertId()
t.Assert(n, 1)
one, err := db.Model(table).WherePri(1).One()
t.AssertNil(err)
t.Assert(one[`id`], `1`)
t.Assert(one[`passport`], `user_1`)
t.Assert(one[`password`], `pass_1`)
t.Assert(one[`nickname`], ``)
t.Assert(one[`create_time`], ``)
})
}
func Test_Model_Insert_Data_LIst_DTO(t *testing.T) {
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"dto:true"`
Id interface{}
Passport interface{}
Password interface{}
Nickname interface{}
CreateTime interface{}
}
data := g.Slice{
User{
Id: 1,
Passport: "user_1",
Password: "pass_1",
},
User{
Id: 2,
Passport: "user_2",
Password: "pass_2",
},
}
result, err := db.Model(table).Data(data).Insert()
t.AssertNil(err)
n, _ := result.LastInsertId()
t.Assert(n, 2)
one, err := db.Model(table).WherePri(1).One()
t.AssertNil(err)
t.Assert(one[`id`], `1`)
t.Assert(one[`passport`], `user_1`)
t.Assert(one[`password`], `pass_1`)
t.Assert(one[`nickname`], ``)
t.Assert(one[`create_time`], ``)
one, err = db.Model(table).WherePri(2).One()
t.AssertNil(err)
t.Assert(one[`id`], `2`)
t.Assert(one[`passport`], `user_2`)
t.Assert(one[`password`], `pass_2`)
t.Assert(one[`nickname`], ``)
t.Assert(one[`create_time`], ``)
})
}
func Test_Model_Update_Data_DTO(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"dto:true"`
Id interface{}
Passport interface{}
Password interface{}
Nickname interface{}
CreateTime interface{}
}
data := User{
Id: 1,
Passport: "user_100",
Password: "pass_100",
}
_, err := db.Model(table).Data(data).WherePri(1).Update()
t.AssertNil(err)
one, err := db.Model(table).WherePri(1).One()
t.AssertNil(err)
t.Assert(one[`id`], `1`)
t.Assert(one[`passport`], `user_100`)
t.Assert(one[`password`], `pass_100`)
t.Assert(one[`nickname`], `name_1`)
})
}
func Test_Model_Where_DTO(t *testing.T) {
table := createInitTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
g.Meta `orm:"dto:true"`
Id interface{}
Passport interface{}
Password interface{}
Nickname interface{}
CreateTime interface{}
}
where := User{
Id: 1,
Passport: "user_1",
Password: "pass_1",
}
one, err := db.Model(table).Where(where).One()
t.AssertNil(err)
t.Assert(one[`id`], `1`)
t.Assert(one[`passport`], `user_1`)
t.Assert(one[`password`], `pass_1`)
t.Assert(one[`nickname`], `name_1`)
})
}
func Test_Model_Insert_Data_ForDao(t *testing.T) {
table := createTable()
defer dropTable(table)