Browse Source

阶段完成实体相关的crud

yjp 1 năm trước cách đây
mục cha
commit
9bd6436cb6

+ 1 - 1
binding/dto.go

@@ -40,7 +40,7 @@ func Field[T any](dto DTO, fieldName string) T {
 	return retValue
 }
 
-func ToConcreteDTO[T DTO](object DTO) T {
+func ToConcrete[T DTO](object DTO) T {
 	concrete, ok := object.(T)
 	if !ok {
 		logger.GetInstance().Error(fserr.New("DTO转化失败"))

+ 9 - 0
binding/service/common.go

@@ -0,0 +1,9 @@
+package service
+
+import "git.sxidc.com/go-framework/baize/domain"
+
+type EntityCRUDCallbacks struct {
+	Before  func(object domain.Object) error
+	Success func(object domain.Object) error
+	Error   func(object domain.Object, err error) error
+}

+ 128 - 0
binding/service/entity_crud.go

@@ -0,0 +1,128 @@
+package service
+
+import (
+	"git.sxidc.com/go-framework/baize/api"
+	"git.sxidc.com/go-framework/baize/binding"
+	"git.sxidc.com/go-framework/baize/domain"
+	"git.sxidc.com/go-framework/baize/infrastructure"
+	"git.sxidc.com/go-framework/baize/infrastructure/database"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"git.sxidc.com/service-supports/fserr"
+)
+
+const (
+	DatabaseExecutorOperations  = "operations"
+	DatabaseExecutorDataService = "data_service"
+)
+
+func CommonEntityCreate(tableName string, databaseExecutorType string, callbacks EntityCRUDCallbacks) binding.ServiceFunc[string] {
+	return func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (string, error) {
+		e, ok := objects[0].(domain.Entity)
+		if !ok {
+			return "", fserr.New("需要传递领域对象应该为实体")
+		}
+
+		err := e.GenerateID()
+		if err != nil {
+			return "", err
+		}
+
+		if callbacks.Before != nil {
+			err := callbacks.Before(e)
+			if err != nil {
+				return "", err
+			}
+		}
+
+		err = database.InsertEntity(chooseDatabaseExecutor(databaseExecutorType, i), tableName, e)
+		if err != nil {
+			if callbacks.Error != nil {
+				err := callbacks.Error(e, err)
+				if err != nil {
+					return "", err
+				}
+			}
+
+			return "", err
+		}
+
+		if callbacks.Success != nil {
+			err := callbacks.Success(e)
+			if err != nil {
+				return "", err
+			}
+		}
+
+		return e.ID(), nil
+	}
+}
+
+func CommonEntityDelete(tableName string, databaseExecutorType string, callbacks EntityCRUDCallbacks) binding.ServiceFunc[any] {
+	return func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		e, ok := objects[0].(domain.Entity)
+		if !ok {
+			return nil, fserr.New("需要传递领域对象应该为实体")
+		}
+
+		if strutils.IsStringEmpty(e.ID()) {
+			return nil, fserr.New("领域实体ID为空")
+		}
+
+		if callbacks.Before != nil {
+			err := callbacks.Before(e)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		err := database.DeleteEntity(chooseDatabaseExecutor(databaseExecutorType, i), tableName, e)
+		if err != nil {
+			if callbacks.Error != nil {
+				err := callbacks.Error(e, err)
+				if err != nil {
+					return nil, err
+				}
+			}
+
+			return nil, err
+		}
+
+		if callbacks.Success != nil {
+			err := callbacks.Success(e)
+			if err != nil {
+				return nil, err
+			}
+		}
+
+		return nil, nil
+	}
+}
+
+func CommonEntityUpdate() binding.ServiceFunc[any] {
+	return func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+
+	}
+}
+
+func CommonEntityQuery() binding.ServiceFunc[binding.InfosData[any]] {
+	return func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (binding.InfosData[any], error) {
+
+	}
+}
+
+func CommonEntityQueryByID() binding.ServiceFunc[any] {
+	return func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+
+	}
+}
+
+func chooseDatabaseExecutor(dataExecutorType string, i *infrastructure.Infrastructure) database.Executor {
+	switch dataExecutorType {
+	case DatabaseExecutorOperations:
+		return i.DBOperations()
+	case DatabaseExecutorDataService:
+		return i.DataService()
+	default:
+		return i.DBOperations()
+	}
+}

+ 61 - 0
domain/common_fields.go

@@ -0,0 +1,61 @@
+package domain
+
+import (
+	"git.sxidc.com/go-tools/utils/strutils"
+	"git.sxidc.com/service-supports/fserr"
+	"time"
+)
+
+const (
+	FieldIDLen = 32
+)
+
+type TenantIDField struct {
+	TenantID string `sqlmapping:"column:tenant_id;" sqlresult:"column:tenant_id;"`
+}
+
+func (field *TenantIDField) CheckTenantIDField(domainCNName string, errCode int) error {
+	if strutils.IsStringEmpty(field.TenantID) {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(domainCNName+"租户ID为空"))
+	}
+
+	if len([]byte(field.TenantID)) != FieldIDLen {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(domainCNName+"租户ID长度不正确"))
+	}
+
+	return nil
+}
+
+type UserIDFields struct {
+	CreateUserID     string `sqlmapping:"column:create_user_id;" sqlresult:"column:create_user_id;"`
+	LastUpdateUserID string `sqlmapping:"column:last_update_user_id;" sqlresult:"column:last_update_user_id;"`
+}
+
+func (field *UserIDFields) CheckCreateUserIDField(domainCNName string, errCode int) error {
+	if strutils.IsStringEmpty(field.CreateUserID) {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(domainCNName+"创建用户ID为空"))
+	}
+
+	if len([]byte(field.CreateUserID)) != FieldIDLen {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(domainCNName+"创建用户ID长度不正确"))
+	}
+
+	return nil
+}
+
+func (field *UserIDFields) CheckLastUpdateUserIDField(domainCNName string, errCode int) error {
+	if strutils.IsStringEmpty(field.LastUpdateUserID) {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(domainCNName+"最近更新用户ID为空"))
+	}
+
+	if len([]byte(field.LastUpdateUserID)) != FieldIDLen {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(domainCNName+"最近更新用户ID长度不正确"))
+	}
+
+	return nil
+}
+
+type TimeFields struct {
+	CreatedTime     time.Time `sqlmapping:"column:created_time;" sqlresult:"column:created_time;"`
+	LastUpdatedTime time.Time `sqlmapping:"column:last_updated_time;" sqlresult:"column:last_updated_time;"`
+}

+ 67 - 0
domain/entity.go

@@ -0,0 +1,67 @@
+package domain
+
+import (
+	"git.sxidc.com/go-framework/baize/infrastructure/database/sql"
+	"git.sxidc.com/go-framework/baize/tag/sql/sql_mapping"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"git.sxidc.com/service-supports/fserr"
+)
+
+type ConditionFieldCallback func(conditions *sql.Conditions, fieldName string, columnName string, value any) (hasDeal bool)
+
+type Entity interface {
+	DomainCNName() string
+	GenerateID() error
+	ID() string
+	CheckID(domainCNName string, errCode int) error
+	QueryDBConditions(callback ConditionFieldCallback) sql.Conditions
+}
+
+type BaseEntity struct {
+	ID string `sqlmapping:"column:id;key;" sqlresult:"column:id;"`
+}
+
+func (e *BaseEntity) DomainCNName() string {
+	return "基础实体"
+}
+
+func (e *BaseEntity) GenerateID() {
+	e.ID = strutils.SimpleUUID()
+}
+
+func (e *BaseEntity) GetID() string {
+	return e.ID
+}
+
+func (e *BaseEntity) CheckID(errCode int) error {
+	if strutils.IsStringEmpty(e.ID) {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(e.DomainCNName()+"ID为空"))
+	}
+
+	if len([]byte(e.ID)) != FieldIDLen {
+		return fserr.WithCode(nil, errCode, fserr.MsgOption(e.DomainCNName()+"ID长度不正确"))
+	}
+
+	return nil
+}
+
+func (e *BaseEntity) QueryDBConditions(callback ConditionFieldCallback) (*sql.Conditions, error) {
+	fields, err := sql_mapping.DefaultUsage(e)
+	if err != nil {
+		return nil, err
+	}
+
+	conditions := sql.NewConditions()
+	for _, field := range fields {
+		hasDeal := false
+		if callback != nil {
+			hasDeal = callback(conditions, field.FieldName, field.ColumnName, field.Value)
+		}
+
+		if !hasDeal {
+			conditions.Equal(field.ColumnName, field.Value)
+		}
+	}
+
+	return conditions, nil
+}

+ 31 - 13
domain/object.go

@@ -9,8 +9,12 @@ import (
 
 type Object interface{}
 
+func HasField(object Object, fieldName string) bool {
+	return hasField(object, fieldName)
+}
+
 func SetField[T any](object Object, fieldName string, value T) {
-	fieldValue, err := getObjectFieldValue(object, fieldName)
+	fieldValue, err := getFieldValue(object, fieldName)
 	if err != nil {
 		logger.GetInstance().Error(err)
 		return
@@ -25,32 +29,28 @@ func SetField[T any](object Object, fieldName string, value T) {
 	fieldValue.Set(reflect.ValueOf(value))
 }
 
-func Field[T any](object Object, fieldName string) T {
+func Field[T any](object Object, fieldName string) (T, error) {
 	var zero T
 
-	fieldValue, err := getObjectFieldValue(object, fieldName)
+	fieldValue, err := getFieldValue(object, fieldName)
 	if err != nil {
-		logger.GetInstance().Error(err)
-		return zero
+		return zero, err
 	}
 
 	if !fieldValue.IsValid() {
 		err := fserr.New("object字段" + fieldName + "无法赋值")
-		logger.GetInstance().Error(err)
-		return zero
+		return zero, err
 	}
 
 	retValue, ok := fieldValue.Interface().(T)
 	if !ok {
-		err := fserr.New("object字段" + fieldName + "无法转换类型")
-		logger.GetInstance().Error(err)
-		return zero
+		return zero, err
 	}
 
-	return retValue
+	return retValue, nil
 }
 
-func ToConcreteObject[T Object](object Object) T {
+func ToConcrete[T Object](object Object) T {
 	concrete, ok := object.(T)
 	if !ok {
 		logger.GetInstance().Error(fserr.New("领域对象转化失败"))
@@ -62,7 +62,25 @@ func ToConcreteObject[T Object](object Object) T {
 	return concrete
 }
 
-func getObjectFieldValue(object Object, fieldName string) (*reflect.Value, error) {
+func hasField(object Object, fieldName string) bool {
+	if object == nil {
+		return false
+	}
+
+	objectValue := reflect.ValueOf(object)
+	if reflectutils.IsValueStructOrStructPointer(objectValue) {
+		return false
+	}
+
+	fieldValue := reflectutils.PointerValueElem(objectValue).FieldByName(fieldName)
+	if !fieldValue.IsValid() {
+		return false
+	}
+
+	return true
+}
+
+func getFieldValue(object Object, fieldName string) (*reflect.Value, error) {
 	if object == nil {
 		return nil, fserr.New("object为nil")
 	}

+ 5 - 5
examples/binding/main.go

@@ -146,7 +146,7 @@ func main() {
 		DTO:          &CreateClassJsonBody{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (string, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 			e.ID = strutils.SimpleUUID()
 
 			err := database.InsertEntity(i.DBOperations(), tableName, e)
@@ -165,7 +165,7 @@ func main() {
 		DTO:          &DeleteClassPathParams{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 
 			err := database.DeleteEntity(i.DBOperations(), tableName, e)
 			if err != nil {
@@ -183,7 +183,7 @@ func main() {
 		DTO:          &UpdateClassJsonBody{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 
 			result, err := database.QueryOne(i.DBOperations(), &sql.QueryOneExecuteParams{
 				TableName:  tableName,
@@ -223,7 +223,7 @@ func main() {
 		DTO:          &QueryClassesQueryParams{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (binding.InfosData[ClassInfo], error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 			pageNo := binding.Field[int](dto, "PageNo")
 			pageSize := binding.Field[int](dto, "PageSize")
 
@@ -268,7 +268,7 @@ func main() {
 		DTO:          &GetClassQueryParams{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (*ClassInfo, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 
 			result, err := database.QueryOne(i.DBOperations(), &sql.QueryOneExecuteParams{
 				TableName:  tableName,

+ 5 - 5
examples/binding_ds/main.go

@@ -108,7 +108,7 @@ func main() {
 		DTO:          &CreateClassJsonBody{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (string, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 			e.ID = strutils.SimpleUUID()
 
 			err := database.InsertEntity(i.DataService(), tableName, e)
@@ -127,7 +127,7 @@ func main() {
 		DTO:          &DeleteClassPathParams{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 
 			err := database.DeleteEntity(i.DataService(), tableName, e)
 			if err != nil {
@@ -145,7 +145,7 @@ func main() {
 		DTO:          &UpdateClassJsonBody{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 
 			result, err := database.QueryOne(i.DataService(), &sql.QueryOneExecuteParams{
 				TableName:  tableName,
@@ -185,7 +185,7 @@ func main() {
 		DTO:          &QueryClassesQueryParams{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (binding.InfosData[ClassInfo], error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 			pageNo := binding.Field[int](dto, "PageNo")
 			pageSize := binding.Field[int](dto, "PageSize")
 
@@ -230,7 +230,7 @@ func main() {
 		DTO:          &GetClassQueryParams{},
 		Objects:      []domain.Object{&Class{}},
 		ServiceFunc: func(c *api.Context, dto binding.DTO, objects []domain.Object, i *infrastructure.Infrastructure) (*ClassInfo, error) {
-			e := domain.ToConcreteObject[*Class](objects[0])
+			e := domain.ToConcrete[*Class](objects[0])
 
 			result, err := database.QueryOne(i.DataService(), &sql.QueryOneExecuteParams{
 				TableName:  tableName,

+ 0 - 61
examples/common_crud/main.go

@@ -1,61 +0,0 @@
-package main
-
-//import (
-//DEATH "github.com/vrecan/death"
-//"go-framework/baize"
-//"syscall"
-//)
-
-//type Class struct {
-//	domain.IDField
-//	Name string `write:"column:name;" read:"column:name;condition:'${column} LIKE %${value}%'" cache:"key:${field.IDField}"`
-//	domain.TenantIDField
-//	domain.UserIDFields
-//	domain.TimeFields
-//}
-//
-//type Student struct {
-//	domain.IDField
-//	Name string `write:"column:name;" read:"column:name;condition:'${column} LIKE %${value}%'"`
-//	Age  int    `write:"column:age;" read:"column:age;condition:'${column} LIKE %${value}%'" cache:"key:${field.IDField}"`
-//	domain.TenantIDField
-//	domain.UserIDFields
-//	domain.TimeFields
-//}
-
-func main() {
-	//app, err := baize.NewApplication("10100", WithDB(config))
-	//if err != nil {
-	//	panic(err)
-	//}
-	//
-	//app.RegisterRouter("v1", middlewares...).
-	//	RegisterCommonCrud(&Class{}).
-	//	RegisterCrud(&common.Crud{
-	//		Api:          common.CrudApi{},
-	//		Service:      common.CrudService{},
-	//		DomainObject: &Student{},
-	//	}).
-	//	RegisterRelation(&common.Relation{
-	//		Type:              common.One2Many,
-	//		LeftDomainEntity:  &Class{},
-	//		RightDomainEntity: &Student{},
-	//	})
-	//
-	//go func() {
-	//	err := app.Start()
-	//	if err != nil {
-	//		panic(err)
-	//	}
-	//}()
-	//
-	//defer func() {
-	//	err := app.Finish()
-	//	if err != nil {
-	//		panic(err)
-	//	}
-	//}()
-	//
-	//death := DEATH.NewDeath(syscall.SIGINT, syscall.SIGTERM)
-	//_ = death.WaitForDeath()
-}

+ 0 - 5
examples/crud/main.go

@@ -1,5 +0,0 @@
-package main
-
-func main() {
-
-}

+ 0 - 5
examples/relation/main.go

@@ -1,5 +0,0 @@
-package main
-
-func main() {
-
-}