浏览代码

完成远端关联

yjp 1 年之前
父节点
当前提交
c2a20507ec

+ 56 - 127
convenient/relation/remote/service.go

@@ -14,9 +14,9 @@ import (
 	"git.sxidc.com/service-supports/fserr"
 )
 
-func UpdateFromExist(middleTableName string,
-	fromTableName string, fromDomainCNName string, fromRelationFieldName string, fromRelationColumnName string,
-	toTableName string, toRelationColumnName string) binding.ServiceFunc[any] {
+func Update(middleTableName string,
+	fromRemote bool, fromTableName string, fromDomainCNName string, fromRelationFieldName string, fromRelationColumnName string,
+	toRemote bool, toTableName string, toRelationColumnName 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 {
@@ -36,17 +36,19 @@ func UpdateFromExist(middleTableName string,
 			return nil, err
 		}
 
-		// from存在性校验
-		fromExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
-			TableName:  fromTableName,
-			Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()),
-		})
-		if err != nil {
-			return nil, err
-		}
+		if !fromRemote {
+			// from存在性校验
+			fromExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
+				TableName:  fromTableName,
+				Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()),
+			})
+			if err != nil {
+				return nil, err
+			}
 
-		if !fromExist {
-			return nil, fserr.New(fromEntity.DomainCNName() + "不存在")
+			if !fromExist {
+				return nil, fserr.New(fromEntity.DomainCNName() + "不存在")
+			}
 		}
 
 		if !domain.HasField(object, fromRelationFieldName) {
@@ -82,16 +84,18 @@ func UpdateFromExist(middleTableName string,
 				return nil
 			}
 
-			toCount, err := database.Count(dbExecutor, &sql.CountExecuteParams{
-				TableName:  toTableName,
-				Conditions: sql.NewConditions().In(entity.ColumnID, toIDs),
-			})
-			if err != nil {
-				return err
-			}
+			if !toRemote {
+				toCount, err := database.Count(dbExecutor, &sql.CountExecuteParams{
+					TableName:  toTableName,
+					Conditions: sql.NewConditions().In(entity.ColumnID, toIDs),
+				})
+				if err != nil {
+					return err
+				}
 
-			if int(toCount) != len(toIDs) {
-				return fserr.New("部分{{ $toCNName }}不存在")
+				if int(toCount) != len(toIDs) {
+					return fserr.New("部分{{ $toCNName }}不存在")
+				}
 			}
 
 			tableRows := make([]sql.TableRow, len(toIDs))
@@ -119,8 +123,8 @@ func UpdateFromExist(middleTableName string,
 	}
 }
 
-func QueryFromExist[TI any](middleTableName string,
-	fromTableName string, fromRelationColumnName string,
+func QueryToExist[TI any](middleTableName string,
+	fromRemote bool, fromTableName string, fromRelationColumnName string,
 	toTableName string, toRelationColumnName string) binding.ServiceFunc[response.InfosData[TI]] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[TI], error) {
 		errResponse := response.InfosData[TI]{
@@ -148,17 +152,19 @@ func QueryFromExist[TI any](middleTableName string,
 			return errResponse, fserr.New("领域对象不是实体")
 		}
 
-		// from存在性校验
-		fromExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
-			TableName:  fromTableName,
-			Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()),
-		})
-		if err != nil {
-			return errResponse, err
-		}
+		if !fromRemote {
+			// from存在性校验
+			fromExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
+				TableName:  fromTableName,
+				Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()),
+			})
+			if err != nil {
+				return errResponse, err
+			}
 
-		if !fromExist {
-			return errResponse, fserr.New(fromEntity.DomainCNName() + "不存在")
+			if !fromExist {
+				return errResponse, fserr.New(fromEntity.DomainCNName() + "不存在")
+			}
 		}
 
 		toIDResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{
@@ -209,99 +215,7 @@ func QueryFromExist[TI any](middleTableName string,
 	}
 }
 
-func UpdateFromRemote(middleTableName string,
-	fromRelationFieldName string, fromDomainCNName string, fromRelationColumnName string,
-	toTableName string, toRelationColumnName 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("领域实体为空")
-		}
-
-		dbExecutor := i.DBExecutor()
-
-		fromEntity, ok := object.(entity.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 + "不存在")
-		}
-
-		toIDs, err := domain.Field[[]string](object, fromRelationFieldName)
-		if err != nil {
-			return nil, err
-		}
-
-		if toIDs != nil && len(toIDs) != 0 {
-			for _, toID := range toIDs {
-				err := entity.CheckID(fromDomainCNName, fromRelationFieldName, toID)
-				if err != nil {
-					return nil, err
-				}
-			}
-
-			toIDs = slice.RemoveRepeatElement(toIDs)
-		}
-
-		err = database.Transaction(dbExecutor, func(tx database.Executor) error {
-			err := database.Delete(tx, &sql.DeleteExecuteParams{
-				TableName:  middleTableName,
-				Conditions: sql.NewConditions().Equal(fromRelationColumnName, fromEntity.GetID()),
-			})
-			if err != nil {
-				return err
-			}
-
-			if toIDs == nil || len(toIDs) == 0 {
-				return nil
-			}
-
-			toCount, err := database.Count(dbExecutor, &sql.CountExecuteParams{
-				TableName:  toTableName,
-				Conditions: sql.NewConditions().In(entity.ColumnID, toIDs),
-			})
-			if err != nil {
-				return err
-			}
-
-			if int(toCount) != len(toIDs) {
-				return fserr.New("部分{{ $toCNName }}不存在")
-			}
-
-			tableRows := make([]sql.TableRow, len(toIDs))
-			for index, toID := range toIDs {
-				tableRows[index] = *(sql.NewTableRow().
-					Add(fromRelationColumnName, fromEntity.GetID()).
-					Add(toRelationColumnName, toID))
-			}
-
-			err = database.InsertBatch(tx, &sql.InsertBatchExecuteParams{
-				TableName:     middleTableName,
-				TableRowBatch: tableRows,
-			})
-			if err != nil {
-				return err
-			}
-
-			return nil
-		})
-		if err != nil {
-			return nil, err
-		}
-
-		return nil, nil
-	}
-}
-
-func QueryFromRemote(middleTableName string, fromRelationColumnName string, toRelationColumnName string) binding.ServiceFunc[response.InfosData[string]] {
+func QueryToRemote(middleTableName string, fromRemote bool, fromTableName string, fromRelationColumnName string, toRelationColumnName string) binding.ServiceFunc[response.InfosData[string]] {
 	return func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (response.InfosData[string], error) {
 		errResponse := response.InfosData[string]{
 			Infos: make([]string, 0),
@@ -328,6 +242,21 @@ func QueryFromRemote(middleTableName string, fromRelationColumnName string, toRe
 			return errResponse, fserr.New("领域对象不是实体")
 		}
 
+		if !fromRemote {
+			// from存在性校验
+			fromExist, err := database.CheckExist(dbExecutor, &sql.CheckExistExecuteParams{
+				TableName:  fromTableName,
+				Conditions: sql.NewConditions().Equal(entity.ColumnID, fromEntity.GetID()),
+			})
+			if err != nil {
+				return errResponse, err
+			}
+
+			if !fromExist {
+				return errResponse, fserr.New(fromEntity.DomainCNName() + "不存在")
+			}
+		}
+
 		toIDResults, totalCount, err := database.Query(dbExecutor, &sql.QueryExecuteParams{
 			TableName:     middleTableName,
 			SelectColumns: []string{toRelationColumnName},

+ 37 - 70
convenient/relation/remote/simple.go

@@ -28,15 +28,6 @@ type Simple[I any] struct {
 	// 数据库Schema
 	Schema string
 
-	// 中间表表名
-	MiddleTableName string
-
-	// URL领域相对路径,如/person,后面会自动补充,如/person/右领域path/update
-	LeftDomainPath string
-
-	// URL领域相对路径,如/identity,后面会自动补充,如/identity/左领域path/update
-	RightDomainPath string
-
 	// 更新左实体关联使用的请求参数
 	LeftUpdateJsonBody request.Params
 
@@ -71,48 +62,36 @@ func (simple *Simple[I]) bind(binder *binding.Binder) {
 	if !options.disableLeft {
 		if !options.disableLeftUpdate {
 			// 左到右更新
-			if !simple.LeftRemote {
-				binding.PostBind(binder, &binding.SimpleBindItem[any]{
-					Path:          leftDomainPath + rightDomainPath + "/update",
-					ResponseFunc:  response.SendMsgResponse,
-					RequestParams: simple.LeftUpdateJsonBody,
-					Objects:       []domain.Object{simple.Left},
-					ServiceFunc: UpdateFromExist(middleTableName,
-						leftTableName, simple.Left.DomainCNName(), leftRelationFieldName, leftRelationColumnName,
-						rightTableName, rightRelationColumnName),
-				})
-			} else {
-				binding.PostBind(binder, &binding.SimpleBindItem[any]{
-					Path:          leftDomainPath + rightDomainPath + "/update",
-					ResponseFunc:  response.SendMsgResponse,
-					RequestParams: simple.LeftUpdateJsonBody,
-					Objects:       []domain.Object{simple.Left},
-					ServiceFunc: UpdateFromRemote(middleTableName,
-						simple.Left.DomainCNName(), leftRelationFieldName, leftRelationColumnName,
-						rightTableName, rightRelationColumnName),
-				})
-			}
+			binding.PostBind(binder, &binding.SimpleBindItem[any]{
+				Path:          leftDomainPath + rightDomainPath + "/update",
+				ResponseFunc:  response.SendMsgResponse,
+				RequestParams: simple.LeftUpdateJsonBody,
+				Objects:       []domain.Object{simple.Left},
+				ServiceFunc: Update(middleTableName,
+					simple.LeftRemote, leftTableName, simple.Left.DomainCNName(), leftRelationFieldName, leftRelationColumnName,
+					simple.RightRemote, rightTableName, rightRelationColumnName),
+			})
 		}
 
 		if !options.disableLeftQuery {
 			// 左到右查询
-			if !simple.LeftRemote {
-				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[I]]{
+			if simple.RightRemote {
+				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[string]]{
 					Path:          leftDomainPath + rightDomainPath + "/query",
-					ResponseFunc:  response.SendInfosResponse[I],
+					ResponseFunc:  response.SendInfosResponse[string],
 					RequestParams: simple.LeftQueryQueryParams,
 					Objects:       []domain.Object{simple.Left},
-					ServiceFunc: QueryFromExist[I](middleTableName,
-						leftTableName, leftRelationColumnName,
-						rightTableName, rightRelationColumnName),
+					ServiceFunc:   QueryToRemote(middleTableName, simple.LeftRemote, leftTableName, leftRelationColumnName, rightRelationColumnName),
 				})
 			} else {
-				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[string]]{
+				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[I]]{
 					Path:          leftDomainPath + rightDomainPath + "/query",
-					ResponseFunc:  response.SendInfosResponse[string],
+					ResponseFunc:  response.SendInfosResponse[I],
 					RequestParams: simple.LeftQueryQueryParams,
 					Objects:       []domain.Object{simple.Left},
-					ServiceFunc:   QueryFromRemote(middleTableName, leftRelationColumnName, rightRelationColumnName),
+					ServiceFunc: QueryToExist[I](middleTableName,
+						simple.LeftRemote, leftTableName, leftRelationColumnName,
+						rightTableName, rightRelationColumnName),
 				})
 			}
 		}
@@ -121,55 +100,43 @@ func (simple *Simple[I]) bind(binder *binding.Binder) {
 	if !options.disableRight {
 		if !options.disableRightUpdate {
 			// 右到左更新
-			if !simple.RightRemote {
-				binding.PostBind(binder, &binding.SimpleBindItem[any]{
-					Path:          rightDomainPath + leftDomainPath + "/update",
-					ResponseFunc:  response.SendMsgResponse,
-					RequestParams: simple.RightUpdateJsonBody,
-					Objects:       []domain.Object{simple.Right},
-					ServiceFunc: UpdateFromExist(middleTableName,
-						rightTableName, simple.Right.DomainCNName(), rightRelationFieldName, rightRelationColumnName,
-						leftTableName, leftRelationColumnName),
-				})
-			} else {
-				binding.PostBind(binder, &binding.SimpleBindItem[any]{
-					Path:          rightDomainPath + leftDomainPath + "/update",
-					ResponseFunc:  response.SendMsgResponse,
-					RequestParams: simple.RightUpdateJsonBody,
-					Objects:       []domain.Object{simple.Right},
-					ServiceFunc: UpdateFromRemote(middleTableName,
-						simple.Right.DomainCNName(), rightRelationFieldName, rightRelationColumnName,
-						leftTableName, leftRelationColumnName),
-				})
-			}
+			binding.PostBind(binder, &binding.SimpleBindItem[any]{
+				Path:          rightDomainPath + leftDomainPath + "/update",
+				ResponseFunc:  response.SendMsgResponse,
+				RequestParams: simple.RightUpdateJsonBody,
+				Objects:       []domain.Object{simple.Right},
+				ServiceFunc: Update(middleTableName,
+					simple.RightRemote, rightTableName, simple.Right.DomainCNName(), rightRelationFieldName, rightRelationColumnName,
+					simple.LeftRemote, leftTableName, leftRelationColumnName),
+			})
 		}
 
 		if !options.disableRightQuery {
 			// 右到左查询
-			if !simple.RightRemote {
-				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[I]]{
+			if simple.LeftRemote {
+				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[string]]{
 					Path:          rightDomainPath + leftDomainPath + "/query",
-					ResponseFunc:  response.SendInfosResponse[I],
+					ResponseFunc:  response.SendInfosResponse[string],
 					RequestParams: simple.RightQueryQueryParams,
 					Objects:       []domain.Object{simple.Right},
-					ServiceFunc: QueryFromExist[I](middleTableName,
-						rightTableName, rightRelationColumnName,
-						leftTableName, leftRelationColumnName),
+					ServiceFunc:   QueryToRemote(middleTableName, simple.RightRemote, rightTableName, rightRelationColumnName, leftRelationColumnName),
 				})
 			} else {
-				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[string]]{
+				binding.GetBind(binder, &binding.SimpleBindItem[response.InfosData[I]]{
 					Path:          rightDomainPath + leftDomainPath + "/query",
-					ResponseFunc:  response.SendInfosResponse[string],
+					ResponseFunc:  response.SendInfosResponse[I],
 					RequestParams: simple.RightQueryQueryParams,
 					Objects:       []domain.Object{simple.Right},
-					ServiceFunc:   QueryFromRemote(middleTableName, rightRelationColumnName, leftRelationColumnName),
+					ServiceFunc: QueryToExist[I](middleTableName,
+						simple.RightRemote, rightTableName, rightRelationColumnName,
+						leftTableName, leftRelationColumnName),
 				})
 			}
 		}
 	}
 }
 
-func BindSimple[LI any, RI any](binder *binding.Binder, simple *Simple[LI, RI], opts ...Option) {
+func BindSimple[I any](binder *binding.Binder, simple *Simple[I], opts ...Option) {
 	options := new(Options)
 
 	for _, opt := range opts {

+ 1 - 0
examples/examples/project/application/application.go

@@ -42,6 +42,7 @@ var applications = []Service{
 	&service.Family{},
 	&service.StudentAndFamily{},
 	&service.StudentAndIdentity{},
+	&service.StudentAndHobby{},
 }
 
 func Start() error {

+ 36 - 0
examples/examples/project/application/domain/hobby/entity.go

@@ -0,0 +1,36 @@
+package hobby
+
+import (
+	"git.sxidc.com/go-framework/baize/framwork/domain/entity"
+)
+
+type Entity struct {
+	entity.Base
+	StudentIDs []string `sqlmapping:"-" sqlresult:"-"`
+}
+
+func (e *Entity) DomainCNName() string {
+	return "爱好"
+}
+
+func (e *Entity) DomainCamelName() string {
+	return "Hobby"
+}
+
+func (e *Entity) ForCreate() error {
+	err := e.CheckFieldID(e.DomainCNName())
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (e *Entity) ForUpdate() error {
+	err := e.CheckFieldID(e.DomainCNName())
+	if err != nil {
+		return err
+	}
+
+	return nil
+}

+ 16 - 0
examples/examples/project/application/domain/hobby/request_params.go

@@ -0,0 +1,16 @@
+package hobby
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/binding/request"
+)
+
+type (
+	UpdateStudentsOfHobbyJsonBody struct {
+		request.IDJsonBody
+		StudentIDs []string `json:"studentIds" assign:"toField:StudentIDs"`
+	}
+
+	QueryStudentsOfHobbyQueryParams struct {
+		request.BaseQueryWithID
+	}
+)

+ 1 - 0
examples/examples/project/application/domain/student/entity.go

@@ -19,6 +19,7 @@ type Entity struct {
 	Name        string   `sqlmapping:"column:name" sqlresult:"column:name"`
 	FamilyID    string   `sqlmapping:"column:family_id" sqlresult:"column:family_id"`
 	IdentityIDs []string `sqlmapping:"-" sqlresult:"-"`
+	HobbyIDs    []string `sqlmapping:"-" sqlresult:"-"`
 	entity.TimeFields
 }
 

+ 9 - 0
examples/examples/project/application/domain/student/request_params.go

@@ -48,4 +48,13 @@ type (
 	QueryIdentitiesOfStudentQueryParams struct {
 		request.BaseQueryWithID
 	}
+
+	UpdateHobbiesOfStudentJsonBody struct {
+		request.IDJsonBody
+		HobbyIDs []string `json:"hobbyIds" assign:"toField:HobbyIDs"`
+	}
+
+	QueryHobbiesOfStudentQueryParams struct {
+		request.BaseQueryWithID
+	}
 )

+ 36 - 0
examples/examples/project/application/service/student_and_hobby.go

@@ -0,0 +1,36 @@
+package service
+
+import (
+	"git.sxidc.com/go-framework/baize/convenient/relation/remote"
+	"git.sxidc.com/go-framework/baize/examples/examples/project/application/domain/hobby"
+	"git.sxidc.com/go-framework/baize/examples/examples/project/application/domain/identity"
+	"git.sxidc.com/go-framework/baize/examples/examples/project/application/domain/student"
+	"git.sxidc.com/go-framework/baize/framwork/application"
+)
+
+type StudentAndHobby struct{}
+
+func (app *StudentAndHobby) Init(appInstance *application.App) error {
+	app.v1(appInstance)
+	return nil
+}
+
+func (app *StudentAndHobby) Destroy() error {
+	return nil
+}
+
+func (app *StudentAndHobby) v1(appInstance *application.App) {
+	v1Binder := appInstance.Binder(application.RouterPrefix, "v1")
+
+	remote.BindSimple(v1Binder, &remote.Simple[student.Info]{
+		Left:                  &student.Entity{},
+		Right:                 &hobby.Entity{},
+		LeftRemote:            false,
+		RightRemote:           true,
+		Schema:                dbSchema,
+		LeftUpdateJsonBody:    &student.UpdateHobbiesOfStudentJsonBody{},
+		LeftQueryQueryParams:  &student.QueryHobbiesOfStudentQueryParams{},
+		RightUpdateJsonBody:   &identity.UpdateStudentsOfIdentityJsonBody{},
+		RightQueryQueryParams: &identity.QueryStudentsOfIdentityQueryParams{},
+	})
+}

+ 8 - 0
examples/examples/project/main.go

@@ -60,6 +60,14 @@ import (
 // curl -X POST -H "Content-Type: application/json" -d '{"id":"42b305bb292c4082a3e91a2967fe303c", "studentIds": ["d21d93c7f189441fac5d27f14fdce13b"]}' "http://localhost:31000/example/v1/identity/student/update"
 // curl -X GET "http://localhost:31000/example/v1/identity/student/query?id=42b305bb292c4082a3e91a2967fe303c"
 
+// Student-Hobby
+// curl -X POST -H "Content-Type: application/json" -d '{"id":"fca9ad529fb04d22abd9fe0232c8a462", "hobbyIds": ["42b305bb292c4082a3e91a2967f11111"]}' "http://localhost:31000/example/v1/student/hobby/update"
+// curl -X GET "http://localhost:31000/example/v1/student/hobby/query?id=fca9ad529fb04d22abd9fe0232c8a462"
+
+// Hobby-Student
+// curl -X POST -H "Content-Type: application/json" -d '{"id":"42b305bb292c4082a3e91a2967f11111", "studentIds": ["fca9ad529fb04d22abd9fe0232c8a462"]}' "http://localhost:31000/example/v1/hobby/student/update"
+// curl -X GET "http://localhost:31000/example/v1/hobby/student/query?id=42b305bb292c4082a3e91a2967f11111"
+
 func main() {
 	application.NewApp()
 	defer application.DestroyApp()