Kaynağa Gözat

完成一对一更新

yjp 1 yıl önce
ebeveyn
işleme
fc08900075

+ 10 - 0
convenient/binding/request/common.go

@@ -76,3 +76,13 @@ func (q *BaseQuery) GetPageNo() int {
 func (q *BaseQuery) GetPageSize() int {
 	return q.PageSize
 }
+
+type QueryWithID interface {
+	WithID
+	Query
+}
+
+type BaseQueryWithID struct {
+	IDPath
+	BaseQuery
+}

+ 49 - 4
convenient/entity/service.go

@@ -16,6 +16,11 @@ import (
 
 func Create(tableName string, callbacks *Callbacks[string]) binding.ServiceFunc[string] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (string, error) {
+		object := objects[0]
+		if object == nil {
+			return "", fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		e, ok := objects[0].(domain.Entity)
@@ -58,6 +63,11 @@ func Create(tableName string, callbacks *Callbacks[string]) binding.ServiceFunc[
 
 func Delete(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		e, ok := objects[0].(domain.Entity)
@@ -91,6 +101,11 @@ func Delete(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any
 
 func Update(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		e, ok := objects[0].(domain.Entity)
@@ -105,7 +120,7 @@ func Update(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any
 
 		exist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
 			TableName:  tableName,
-			Conditions: sql.NewConditions().Equal(e.IDColumnName(), e.GetID()),
+			Conditions: sql.NewConditions().Equal(domain.ColumnID, e.GetID()),
 		})
 		if err != nil {
 			return callbackOnErrorReturn(callbacks, e, err, i, nil)
@@ -139,6 +154,15 @@ type ConditionFieldCallback func(conditions *sql.Conditions, fieldName string, c
 
 func Query[O any](tableName string, callbacks *Callbacks[response.InfosData[O]], conditionFieldCallback ConditionFieldCallback) binding.ServiceFunc[response.InfosData[O]] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[O], error) {
+		if params == nil {
+			return response.InfosData[O]{}, fserr.New("请求参数为空")
+		}
+
+		object := objects[0]
+		if object == nil {
+			return response.InfosData[O]{}, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		queryParams, ok := params.(request.Query)
@@ -210,9 +234,15 @@ func Query[O any](tableName string, callbacks *Callbacks[response.InfosData[O]],
 
 func GetByID[O any](tableName string, callbacks *Callbacks[O]) binding.ServiceFunc[O] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (O, error) {
+		var outputZero O
+
+		object := objects[0]
+		if object == nil {
+			return outputZero, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
-		var outputZero O
 		outputZeroValue := reflect.Zero(reflect.TypeOf(outputZero))
 		if outputZeroValue.Kind() == reflect.Pointer {
 			outputZeroValue.Set(reflect.New(outputZeroValue.Type().Elem()))
@@ -235,7 +265,7 @@ func GetByID[O any](tableName string, callbacks *Callbacks[O]) binding.ServiceFu
 
 		result, err := database.QueryOne(dbExecutor, &sql.QueryOneExecuteParams{
 			TableName:  tableName,
-			Conditions: sql.NewConditions().Equal(e.IDColumnName(), e.GetID()),
+			Conditions: sql.NewConditions().Equal(domain.ColumnID, e.GetID()),
 		})
 		if err != nil {
 			return callbackOnErrorReturn(callbacks, e, err, i, outputZero)
@@ -265,6 +295,11 @@ func GetByID[O any](tableName string, callbacks *Callbacks[O]) binding.ServiceFu
 
 func CreateTx(tableName string, callbacks *Callbacks[string]) binding.ServiceFunc[string] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (string, error) {
+		object := objects[0]
+		if object == nil {
+			return "", fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		e, ok := objects[0].(domain.Entity)
@@ -314,6 +349,11 @@ func CreateTx(tableName string, callbacks *Callbacks[string]) binding.ServiceFun
 
 func DeleteTx(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		e, ok := objects[0].(domain.Entity)
@@ -354,6 +394,11 @@ func DeleteTx(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[a
 
 func UpdateTx(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		e, ok := objects[0].(domain.Entity)
@@ -368,7 +413,7 @@ func UpdateTx(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[a
 
 		exist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
 			TableName:  tableName,
-			Conditions: sql.NewConditions().Equal(e.IDColumnName(), e.GetID()),
+			Conditions: sql.NewConditions().Equal(domain.ColumnID, e.GetID()),
 		})
 		if err != nil {
 			return callbackOnErrorReturn(callbacks, e, err, i, nil)

+ 67 - 1
convenient/relation/one2one/service.go

@@ -7,10 +7,76 @@ import (
 	"git.sxidc.com/go-framework/baize/framwork/api"
 	"git.sxidc.com/go-framework/baize/framwork/domain"
 	"git.sxidc.com/go-framework/baize/framwork/infrastructure"
+	"git.sxidc.com/go-framework/baize/framwork/infrastructure/database"
+	"git.sxidc.com/go-framework/baize/framwork/infrastructure/database/sql"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"git.sxidc.com/service-supports/fserr"
 )
 
-func Update(tableName string) binding.ServiceFunc[any] {
+func Update(fromTableName string, fromRelationFieldName string, fromRelationColumnName string, toTableName string, toDomainCNName string) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
+		fromEntity, ok := object.(domain.Entity)
+		if !ok {
+			return nil, fserr.New("领域对象不是实体")
+		}
+
+		// 字段校验
+		err := fromEntity.CheckFieldID(fromEntity.DomainCNName())
+		if err != nil {
+			return nil, err
+		}
+
+		if !domain.HasField(object, fromRelationFieldName) {
+			return nil, fserr.New("关联字段" + fromRelationFieldName + "不存在")
+		}
+
+		// from存在性校验
+		fromExist, err := database.CheckExist(i.DBExecutor(), &sql.CheckExistExecuteParams{
+			TableName:  fromTableName,
+			Conditions: sql.NewConditions().Equal(domain.ColumnID, fromEntity.GetID()),
+		})
+		if err != nil {
+			return nil, err
+		}
+
+		if !fromExist {
+			return nil, fserr.New(fromEntity.DomainCNName() + "不存在")
+		}
+
+		toID, err := domain.Field[string](object, fromRelationFieldName)
+		if err != nil {
+			return nil, err
+		}
+
+		if strutils.IsStringNotEmpty(toID) {
+			// to存在性校验
+			toExist, err := database.CheckExist(i.DBExecutor(), &sql.CheckExistExecuteParams{
+				TableName:  toTableName,
+				Conditions: sql.NewConditions().Equal(domain.ColumnID, toID),
+			})
+			if err != nil {
+				return nil, err
+			}
+
+			if !toExist {
+				return nil, fserr.New(fromEntity.DomainCNName() + "关联的" + toDomainCNName + "不存在")
+			}
+		}
+
+		err = database.Update(i.DBExecutor(), &sql.UpdateExecuteParams{
+			TableName:  toTableName,
+			TableRow:   sql.NewTableRow().Add(fromRelationColumnName, toID),
+			Conditions: sql.NewConditions().Equal(domain.ColumnID, fromEntity.GetID()),
+		})
+		if err != nil {
+			return nil, err
+		}
+
 		return nil, nil
 	}
 }

+ 48 - 43
convenient/relation/one2one/simple.go

@@ -1,9 +1,13 @@
 package one2one
 
 import (
+	"fmt"
 	"git.sxidc.com/go-framework/baize/convenient/binding"
 	"git.sxidc.com/go-framework/baize/convenient/binding/request"
+	"git.sxidc.com/go-framework/baize/convenient/binding/response"
 	"git.sxidc.com/go-framework/baize/framwork/domain"
+	"github.com/iancoleman/strcase"
+	"reflect"
 )
 
 // Simple 关联的Bind参数
@@ -29,29 +33,66 @@ type Simple[LI any, RI any] struct {
 	RightDomainPath string
 
 	// 更新左实体关联使用的请求参数
-	LeftUpdateJsonBody request.Params
+	LeftUpdateJsonBody request.WithID
 
 	// 查询左实体关联使用的请求参数,注意是Query类型
-	LeftQueryQueryParams request.Query
+	LeftQueryQueryParams request.QueryWithID
 
 	// 更新右实体关联使用的请求参数
-	RightUpdateJsonBody request.Params
+	RightUpdateJsonBody request.WithID
 
 	// 查询右实体关联使用的请求参数,注意是Query类型
-	RightQueryQueryParams request.Query
+	RightQueryQueryParams request.QueryWithID
 
 	// 查询左实体带右实体信息使用的请求参数,注意是Query类型
-	LeftQueryWithRightQueryParams request.Query
+	LeftQueryWithRightQueryParams request.QueryWithID
 
 	// 查询右实体带左实体信息使用的请求参数,注意是Query类型
-	RightQueryWithLeftQueryParams request.Query
+	RightQueryWithLeftQueryParams request.QueryWithID
 
 	// 可选配置项,通过WithXXX配置
 	options *Options
 }
 
 func (simple *Simple[LI, RI]) bind(binder *binding.Binder) {
-	//options := simple.options
+	options := simple.options
+
+	leftEntityType := reflect.TypeOf(simple.Left)
+	rightEntityType := reflect.TypeOf(simple.Right)
+
+	leftRelationFieldName := fmt.Sprintf("%sID", strcase.ToCamel(rightEntityType.Name()))
+	rightRelationFieldName := fmt.Sprintf("%sID", strcase.ToCamel(leftEntityType.Name()))
+	leftRelationColumnName := fmt.Sprintf("%s_id", strcase.ToSnake(rightEntityType.Name()))
+	rightRelationColumnName := fmt.Sprintf("%s_id", strcase.ToSnake(leftEntityType.Name()))
+
+	if !options.disableLeft {
+		if !options.disableLeftUpdate {
+			// 左到右更新
+			binding.PostBind(binder, &binding.SimpleBindItem[any]{
+				Path:          simple.LeftDomainPath + simple.RightDomainPath + "/update",
+				ResponseFunc:  response.SendMsgResponse,
+				RequestParams: simple.LeftUpdateJsonBody,
+				Objects:       []domain.Object{simple.Left},
+				ServiceFunc: Update(simple.LeftTableName, leftRelationFieldName, leftRelationColumnName,
+					simple.RightTableName, simple.Right.DomainCNName()),
+			})
+		}
+	}
+
+	if !options.disableRight {
+		if !options.disableRightUpdate {
+			// 右到左更新
+			binding.PostBind(binder, &binding.SimpleBindItem[any]{
+				Path:          simple.RightDomainPath + simple.LeftDomainPath + "/update",
+				ResponseFunc:  response.SendMsgResponse,
+				RequestParams: simple.RightUpdateJsonBody,
+				Objects:       []domain.Object{simple.Right},
+				ServiceFunc: Update(simple.RightTableName, rightRelationFieldName, rightRelationColumnName,
+					simple.LeftTableName, simple.Left.DomainCNName()),
+			})
+		}
+	}
+
 }
 
 func BindSimple[LI any, RI any](binder *binding.Binder, simple *Simple[LI, RI], opts ...Option) {
@@ -69,18 +110,6 @@ func BindSimple[LI any, RI any](binder *binding.Binder, simple *Simple[LI, RI],
 type Option func(options *Options)
 
 type Options struct {
-	// 左实体中指向右实体的字段
-	leftRelationField string
-
-	// 右实体中指向左实体的字段
-	rightRelationField string
-
-	// 左实体中指向右实体的列名
-	leftRelationColumn string
-
-	// 右实体中指向左实体的列名
-	rightRelationColumn string
-
 	// 关闭左侧到右侧关联
 	disableLeft bool
 
@@ -106,30 +135,6 @@ type Options struct {
 	disableRightWithLeftQuery bool
 }
 
-func WithLeftRelationField(leftRelationField string) Option {
-	return func(options *Options) {
-		options.leftRelationField = leftRelationField
-	}
-}
-
-func WithRightRelationField(rightRelationField string) Option {
-	return func(options *Options) {
-		options.rightRelationField = rightRelationField
-	}
-}
-
-func WithLeftRelationColumn(leftRelationColumn string) Option {
-	return func(options *Options) {
-		options.leftRelationColumn = leftRelationColumn
-	}
-}
-
-func WithRightRelationColumn(rightRelationColumn string) Option {
-	return func(options *Options) {
-		options.rightRelationColumn = rightRelationColumn
-	}
-}
-
 func WithDisableLeft() Option {
 	return func(options *Options) {
 		options.disableLeft = true

+ 19 - 0
convenient/value_object/service.go

@@ -16,6 +16,11 @@ import (
 
 func Create(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		valueObject, ok := objects[0].(domain.ValueObject)
@@ -53,6 +58,11 @@ func Create(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any
 
 func Delete(tableName string, callbacks *Callbacks[any]) binding.ServiceFunc[any] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (any, error) {
+		object := objects[0]
+		if object == nil {
+			return nil, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		valueObject, ok := objects[0].(domain.ValueObject)
@@ -88,6 +98,15 @@ type ConditionFieldCallback func(conditions *sql.Conditions, fieldName string, c
 
 func Query[O any](tableName string, callbacks *Callbacks[response.InfosData[O]], conditionFieldCallback ConditionFieldCallback) binding.ServiceFunc[response.InfosData[O]] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[O], error) {
+		if params == nil {
+			return response.InfosData[O]{}, fserr.New("请求参数为空")
+		}
+
+		object := objects[0]
+		if object == nil {
+			return response.InfosData[O]{}, fserr.New("领域实体为空")
+		}
+
 		dbExecutor := i.DBExecutor()
 
 		queryParams, ok := params.(request.Query)

+ 0 - 83
examples/example_domain/class/entity.go

@@ -1,83 +0,0 @@
-package class
-
-import (
-	"git.sxidc.com/go-framework/baize/domain"
-	"git.sxidc.com/go-tools/utils/strutils"
-	"git.sxidc.com/service-supports/fserr"
-)
-
-const (
-	TableName = "test.classes"
-)
-
-const (
-	ColumnName       = "name"
-	ColumnStudentNum = "student_num"
-)
-
-const (
-	fieldNameMaxLen = 128
-)
-
-type Entity struct {
-	domain.BaseEntity
-	Name       string `sqlmapping:"column:name" sqlresult:"column:name"`
-	StudentNum int    `sqlmapping:"column:student_num;updateClear;" sqlresult:"column:student_num"`
-	domain.TimeFields
-}
-
-func (e *Entity) DomainCNName() string {
-	return "班级"
-}
-
-func (e *Entity) ForCreate() error {
-	err := e.CheckFieldID(e.DomainCNName())
-	if err != nil {
-		return err
-	}
-
-	err = e.checkFieldName()
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (e *Entity) ForUpdate() error {
-	err := e.CheckFieldID(e.DomainCNName())
-	if err != nil {
-		return err
-	}
-
-	err = e.checkUpdateFields()
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (e *Entity) checkFieldName() error {
-	if strutils.IsStringEmpty(e.Name) {
-		return fserr.New(e.DomainCNName() + "名称为空")
-	}
-
-	if len(e.Name) > fieldNameMaxLen {
-		return fserr.New(e.DomainCNName() + "名称超出限定长度")
-	}
-
-	return nil
-}
-
-func (e *Entity) checkUpdateFields() error {
-	if strutils.AllBlank(e.Name) {
-		return fserr.New(e.DomainCNName() + "没有传递需要更新的字段")
-	}
-
-	if strutils.IsStringNotEmpty(e.Name) && len(e.Name) > fieldNameMaxLen {
-		return fserr.New(e.DomainCNName() + "名称超出限定长度")
-	}
-
-	return nil
-}

+ 0 - 12
examples/example_domain/class/info.go

@@ -1,12 +0,0 @@
-package class
-
-import (
-	"git.sxidc.com/go-framework/baize/application"
-)
-
-type Info struct {
-	application.InfoIDField
-	Name       string `json:"name" sqlresult:"column:name"`
-	StudentNum int    `json:"studentNum" sqlresult:"column:student_num"`
-	application.InfoTimeFields
-}

+ 0 - 32
examples/example_domain/class/request_params.go

@@ -1,32 +0,0 @@
-package class
-
-import (
-	"git.sxidc.com/go-framework/baize/convenient/binding/request"
-)
-
-type (
-	CreateJsonBody struct {
-		Name       string `json:"name" binding:"required" assign:"toField:Name"`
-		StudentNum int    `json:"studentNum" binding:"required" assign:"toField:StudentNum"`
-	}
-
-	DeletePathParams struct {
-		request.IDPath
-	}
-
-	UpdateJsonBody struct {
-		request.IDJsonBody
-		Name       string `json:"name" assign:"toField:Name"`
-		StudentNum int    `json:"studentNum" assign:"toField:StudentNum"`
-	}
-
-	QueryQueryParams struct {
-		Name       string `form:"name" assign:"toField:Name"`
-		StudentNum int    `form:"studentNum" assign:"toField:StudentNum"`
-		request.BaseQuery
-	}
-
-	GetByIDQueryParams struct {
-		request.IDQuery
-	}
-)

+ 71 - 0
examples/examples/project/deployment/resources/resources.yaml

@@ -54,6 +54,77 @@ spec:
 
 ---
 
+kind: DataContainer
+spec:
+  namespace: baize
+  data_source: baize
+  name: test.students
+  spec:
+    table_name: test.students
+    columns:
+      - name: id
+        type: varchar(32)
+        comment: id
+        primary_key: true
+      - name: name
+        type: varchar(128)
+        comment: 姓名
+        not_null: true
+        index: true
+      - name: family_id
+        type: varchar(32)
+        comment: 家庭ID
+        not_null: true
+        index: true
+      - name: created_time
+        type: "timestamp with time zone"
+        comment: 创建时间
+        not_null: true
+      - name: last_updated_time
+        type: "timestamp with time zone"
+        comment: 最近更新时间
+        not_null: true
+
+---
+
+kind: DataContainer
+spec:
+  namespace: baize
+  data_source: baize
+  name: test.families
+  spec:
+    table_name: test.families
+    columns:
+      - name: id
+        type: varchar(32)
+        comment: id
+        primary_key: true
+      - name: father
+        type: varchar(128)
+        comment: 父亲姓名
+        not_null: true
+        index: true
+      - name: mother
+        type: varchar(128)
+        comment: 母亲姓名
+        not_null: true
+        index: true
+      - name: student_id
+        type: varchar(32)
+        comment: 家庭ID
+        not_null: true
+        index: true
+      - name: created_time
+        type: "timestamp with time zone"
+        comment: 创建时间
+        not_null: true
+      - name: last_updated_time
+        type: "timestamp with time zone"
+        comment: 最近更新时间
+        not_null: true
+
+---
+
 kind: DataContainer
 spec:
   namespace: baize

+ 0 - 1
framwork/domain/entity.go

@@ -10,7 +10,6 @@ type Entity interface {
 	GenerateID() error
 	GetID() string
 	CheckFieldID(domainCNName string) error
-	IDColumnName() string
 	ForCreate() error
 	ForUpdate() error
 }