• 只需要改造一下实体类,以后再也不用写SQL了


    只需要改造一下实体类,以后再也不用写SQL了

    前情提要:此篇文章写的比较详细,可能会给各位读者一些启发。

    现状分析

    • 在写业务时,每新增一个表,都要对该表进行增删改查的SQL编写。
    • 如果一个表的字段非常多,例如:50多个字段。在写CURD的时候需要对每一个字段进行核对,包括字段名,字段值。一旦位置写错了,再次核对又要花费大量的时间。
    • 前端表单传入的参数字段值,到后端时需要重新解析,在填入对应的SQL语句位置,例如:插入,更新。很容易出错。
    • 前端绑定表格又要重新又要重新对照字段。

    以上会用大量的时间花费在写SQL,对照字段,绑定字段,增加了许多重复的工作量。

    现状示例

    1. 建立人员表M.T.Person表,包含三个字段名称,年龄,身份证。

    • 通常前缀M.T包名代表功能架构名,Person代表具体功能表名。
    • 通常字段前缀习惯加上包名+表名缩写的前缀,例如,这里MT只代前缀。(为了模拟大部分表的现状,所以这里加了前缀,实际上没有必要加。)
    Class M.T.Person Extends %Persistent [ SqlTableName = Person ]
    {
    
    Property MTName As %String [ SqlFieldName = MT_Name ];
    
    Property MTAge As %Integer [ SqlFieldName = MT_Age ];
    
    Property MTNo As %String [ SqlFieldName = MT_No ];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2. 新增一条数据,也就是插入的情况。

    在这里插入图片描述

    • 前端

    在这里插入图片描述

    this.$axios.get("", {
      params: {
        ClassName: "M.Person",
        MethodName: "Insert",
        pJson: JSON.stringify(this.editForm)
      }
    }).then(res => {
      this.queryBySql()
      this.$message({
        showClose: true,
        message: '恭喜你,操作成功',
        type: 'success'
      });
      this.dialogVisible = false
      this.resetForm(formName)
    })
      
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    传统的操作方式是:

    1. 前端需要把表单参数字段组成串传入进来,(JSON或者带分割的字符串)。
    2. 后端在JSON或分割的字符串,解析成变量。
    3. 在把对应的字段变量,按照写的SQL语句字段顺序,填入对应的INSERT值。
    • 后端
    ClassMethod Insert(pJson As %Library.DynamicObject)
    {
    	s name = pJson.name
    	s age = pJson.age
    	s no = pJson.no
    	&sql(insert into M_T.Person (MT_Name, MT_Age, MT_No) values(:name, :age, :no))
    	q SQLCODE
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. 获取单条数据内容,也是就是根据ID获取该行数据信息。一般用于更新数据前读取该条数据。

    在这里插入图片描述

    传统的操作方式是:

    1. 从表格获取到该行ID
    2. 传入后端查询到行条数据的所有字段信息。
    3. 把查到的字段组装成JSON或拼串返回给前端。
    4. 前端根据返回的JSON或字符串在写入到对应表单。
    ClassMethod GetDataById(pJson As %Library.DynamicObject = {{}})
    {
    	s id = pJson.id
    	s data = ^M.T.PersonD(id)
    	s name = $lg(data, 2)
    	s age = $lg(data, 3)
    	s no = $lg(data, 4)
    	s obj = {}
    	s obj.name = name
    	s obj.age = age
    	s obj.no = no
    	s obj.id = id
    	q obj
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4. 更新数据,也就是UPDATE也需要把对应的字段和ID传入后端进行匹配。

    在这里插入图片描述

    传统的操作方式是:

    1. 获取要更新的数据信息和ID。把表单参数字段组成串传入进来,(JSON或者带分割的字符串)。
    2. 后端在JSON或分割的字符串,解析成变量。
    3. 在把对应的字段变量,按照写的SQL语句字段顺序,填入对应的UPDATE值。
    ClassMethod Update(pJson As %Library.DynamicObject)
    {
    	s id = pJson.id
    	s name = pJson.name
    	s age = pJson.age
    	s no = pJson.no
    	&sql(update M_T.Person set MT_Name = :name, MT_Age = :age, MT_No = :no where %ID = :id)
    	q SQLCODE
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    5. 删除数据,也就是根据ID删除数据。

    在这里插入图片描述

    传统的操作方式是:

    1. 获取要删除的行ID
    2. 后端根据ID执行SQL
    ClassMethod Delete(pJson As %Library.DynamicObject)
    {
    	s id = pJson.id
    	&sql(delete M_T.Person where ID = :id)
    	q SQLCODE
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    6. 查询列表数据

    在这里插入图片描述

    传统的操作方式是:

    1. 后端查询前端需要的字段。
    2. 把字段拼成JSON数组返回到前端。
    3. 前端根据返回的数组,解析对应的字段填充到表格。
    ClassMethod QueryBySql(pJson As %Library.DynamicObject = {{}})
    {
    	s name = pJson.name
    	s sql = "SELECT ID,MT_Name, MT_Age, MT_No FROM M_T.Person "
    	if (name '= "") {
    		s sql = sql _ " where MT_Name = '" _ name _"'"
    	}
    	s mStatement = ##class(%SQL.Statement).%New()
    	s sc = mStatement.%Prepare(.sql)
    	s rs = mStatement.%Execute()
    	
    	s array = []
    	while rs.%Next() {
    		s name = rs.%Get("MT_Name")
    		s age = rs.%Get("MT_Age")
    		s no = rs.%Get("MT_No")
    		s id = rs.%Get("ID")
    		s obj = {}
    		s obj.name = name
    		s obj.age = age
    		s obj.no = no
    		s obj.id = id
    		d array.%Push(obj)
    	}
    	q array
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    现状总结

    首先以上6步,介绍了传统方式的表的基本操作,新增,修改,删除,查询单条数据,查询列表数据。

    我们也发现前几乎每一步都涉及到组装SQL,对照字段。

    • 前端根据对照的内容绑定表单或表格。
    • 后端根据前端的字段,解析,然后组装SQL执行。

    思考

    前端标识名称年龄身份证
    前端idnameageno
    后端IDMT_NameMT_AgeMT_No

    我们能否通过对照字段关系把SQL组装一下,从而到达不用每次前后端交互,都要组装,解析,编写SQL呢,避免这些耗时有无意义的操作呢?

    方案

    建立映射

    1. 为了作为对照我们建立一个分数Score表。
    Class M.T.Score Extends %Persistent [ SqlTableName = Score ]
    {
    
    Property MTMath As %String [ SqlFieldName = MT_Math ];
    
    Property MTChinese As %String [ SqlFieldName = MT_Chinese ];
    
    Property MTEnglish As %String [ SqlFieldName = MT_English ];
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 通过别名建立对应映射字段。

    注:这里的映射字段指的是前端需要的属性。因为我们的字段都带有前缀,所以前端对照时一般会不带前缀取更规范的命名。所以需要对照。

    Property MTMath As %String [ Aliases = {math}, SqlFieldName = MT_Math ];
    
    Property MTChinese As %String [ Aliases = {chinese}, SqlFieldName = MT_Chinese ];
    
    Property MTEnglish As %String [ Aliases = {english}, SqlFieldName = MT_English ];
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 建立映射类M.Map通过表名,字段的别名与字段的属性名写个方法对照起来。

    目的:

    • 给前端传入后端的找到对应属性写SQL
    • 后端返回给前端所以的表单字段名。
    ClassMethod QueryFieldMap(className)
    {
    	#; 包名
    	s schema = $p(className, ".", 1, * - 1)
    	
    	#; 表名
    	s table = $p(className, ".", *)
    	
    	#; 将包名替换为带下划线的架构名
    	s schema = $replace(schema, ".", "_")
    
    	s obj = ##class(%Library.DynamicObject).%New()  
    	s sql = "SELECT * FROM INFORMATION_SCHEMA.Columns where TABLE_NAME  = '"_table _"' AND TABLE_SCHEMA = '"_schema_"'"
    	s mStatement = ##class(%SQL.Statement).%New()
    	s status = mStatement.%Prepare(.sql)
    	$$$ThrowOnError(status)
    	s result = mStatement.%Execute()
    	
    	while result.%Next() {
    		
    		#; 取字段名称
    		s fieldName =  result.%Get("COLUMN_NAME")
    		
    		#; 取字别名
    		s propertyName = $replace(fieldName, "_", "")
    		s alies = $g(^oddDEF(className, "a",propertyName, 58))
    
    		#; 别名不为空取别名,否则取字段名
    		s key = $s(alies '= "" : alies, 1 : fieldName)
    
    		d obj.%Set(key, fieldName)
    	}
    
        q obj
    }
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    IMP>w ##class(M.Map).QueryFieldMap("M.T.Score").%ToJSON()
    {"ID":"ID","chinese":"MT_Chinese","english":"MT_English","math":"MT_Math"}
    
    • 1
    • 2
    1. 因为我们需要根据实体表自动生成对照,所里需要代码生成器构造一个方法。
    • '%class.Abstract因为代码生成器为编译时自动生成。所以映射的类要建立为抽象类,不为自身生成代码。
    • %class.ClassType '= "persistent" ,这只是个标识,用于控制哪些实体类生成映射。
    ClassMethod MapField() [ CodeMode = objectgenerator ]
    {
    	#; 不是抽象类直接退出
    	if '%class.Abstract {
    
    		#; 获取类名,如果类不声明关键字 类型为 ClassType = persistent 则退出
    		s className = %class.Name
    		q:(%class.ClassType '= "persistent") $$$OK
    		
    		d %code.WriteLine(" s obj = ..QueryFieldMap("""_ className _""")") 
    	    d %code.WriteLine(" q obj")   
    	}
        q $$$OK
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 改造Score类,这里要注意增加类型ClassType = persistent,与继承M.Map映射类。
    • 因为Score类不是抽象类,并且ClassType = persistent,所以编译时会自动为Score生成映射类代码。
    Class M.T.Score Extends (%Persistent, M.Map) [ ClassType = persistent, SqlRowIdName = id, SqlTableName = Score ]
    {
    
    Property MTMath As %String [ Aliases = {math}, SqlFieldName = MT_Math ];
    
    Property MTChinese As %String [ Aliases = {chinese}, SqlFieldName = MT_Chinese ];
    
    Property MTEnglish As %String [ Aliases = {english}, SqlFieldName = MT_English ];
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 我们调用一下方法验证一下。
    IMP>w ##class(M.T.Score).MapField().%ToJSON()
    {"id":"id","chinese":"MT_Chinese","english":"MT_English","math":"MT_Math"}
    
    • 1
    • 2

    查询单条数据

    逻辑:

    1. 先获取映射。
    2. 根据映射遍历生成组装的SQL
    3. 执行SQL得到映射好的JSON
    4. JSON转对象返回。
    ClassMethod Data(id As %Integer, tableName As %String) As %DynamicObject [ SqlProc ]
    {
    	#; 获取类名
    	s className = $replace(tableName, "_", ".")
    	
    	#; 获取映射
    	s mapJson = $classmethod(className, "MapField")
    
    	#; 组装查询SQL字符串
    	s str = "json_object("
    	s iter = mapJson.%GetIterator()
    	while iter.%GetNext(.key, .value) {
    		continue:(mapJson.%GetTypeOf(key) = "unassigned") 
    		s str = str _ "'" _key _ "'" _ ":" _ value _ ","
    
    	} 
    	
    	#; 删除最后一个逗号
    	s str = $e(str, 1, * - 1)
    	s str = str _ ")  as json "
    	s sql = "SELECT  " _ str _ " FROM " _ tableName _ " where %ID = ?"
    	
    	#; 执行查询
    	s mStatement = ##class(%SQL.Statement).%New()
    	s status = mStatement.%Prepare(.sql)
    	s result = mStatement.%Execute(id)
    	
    	#; 获取表的数据
    	while result.%Next() {
    		s jsonStr = result.%Get("json")
    		s json = {}.%FromJSON(jsonStr)
    	}
    	q json
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在这里插入图片描述

    现在有一条数据,我们通过上述方法查询。

    ClassMethod QueryScoreById(pJson As %Library.DynamicObject)
    {
    	#; 只需要传入对应ID与表明
        q ##class(M.Common.Sql).Data(pJson.id, "M_T.Score")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 返回对照的JSON数组,可直接作用前端表单。
    IMP> w ##class(M.Score).QueryScoreById({"id" : 1}).%ToJSON()
    {"id":1,"chinese":"90","english":"100","math":"80"}
    
    • 1
    • 2

    增加 INSERRT

    • 由于前端新增数据,可能只是某一些字段进行插入,所以要根据前端的映射字段找到后端表的属性字段,再组装SQL,并非把所有字段写成INSERT语句。

    逻辑:

    1. 根据映射字段找到属性字段。
    ClassMethod MapJson2SqlFields(map As %DynamicObject, json As %DynamicObject) As %DynamicObject
    {
        #dim ret as %DynamicObject = {}
        q:(map.%ToJSON() = "{}") json
        
        #; 遍历insert或update的字段
        s iter = json.%GetIterator()
        while iter.%GetNext(.key, .value) {
            continue:(map.%GetTypeOf(key) = "unassigned") 
            
            #; 根据映射字段,获取属性字段
            s newKey = map.%Get(key)   
            d ret.%Set(newKey, value)       
        } 
        q ret
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    IMP 2e1> w ##class(IMP.Common.Sql).MapJson2SqlFields(##class(M.T.Score).MapField(), ##class(M.Score).QueryScoreById({"id":1})).%ToJSON()
    {"id":1,"MT_Chinese":"90","MT_English":"100","MT_Math":"80"}
    
    • 1
    • 2
    1. 获取到表的属性字段后组装INSERT语句。
    ClassMethod Json2SqlInsert(zJson)
    {
        s data = zJson.data
        s table = zJson.table
        
        #; 逗号分割的字段串
        s nameStr = ""
        
        #; 带引号的分割的值串
        s dataStr = ""
        
        #; 把data中的字段与值分组
        s iter = data.%GetIterator()
        while iter.%GetNext(.key, .value) {
            s nameStr = $s(nameStr = "" : key, 1 : nameStr _ "," _ key)
            if ($listvalid(value)){
                if (value = ""){
                    s fmtValue = "NULL"
                }else{
                    s fmtValue = "$LISTFROMSTRING('" _ $lts(value) _ "')"
                }
            }else{
                s fmtValue = $s(value = "" : "NULL" , 1 : "'" _ value _ "'")
            }
            s dataStr = $s(dataStr = "" : fmtValue, 1 : dataStr _ "," _ fmtValue)
        }
        q "INSERT INTO " _ table _ "(" _ nameStr _ ") VALUES (" _ dataStr _ ")"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    w ##class(M.Common.Sql).Json2SqlInsert({"type":"INSERT","table":"M_T.Score","id":"","data":{"MT_Math":90,"MT_Chinese":90,"MT_English":90}})
    INSERT INTO M_T.Score(MT_Math,MT_Chinese,MT_English) VALUES ('90','90','90')
    
    • 1
    • 2
    1. 把得到的SQL语句执行。
    ClassMethod XSQL(sqlStr)
    {
    	#define ThrowSqlException(%str)  throw:((SQLCODE '= 0)&&(SQLCODE '= 100)) ##class(%Exception.SystemException).%New("SQL错误", SQLCODE, , %str _ ":" _ " SQLCODE:"_ SQLCODE  _ " %msg:"_ $g(%msg))
        s sqlStatement = ##class(%SQL.Statement).%New()
        s sqlStatus = sqlStatement.%Prepare(sqlStr)
        $$$ThrowOnError(sqlStatus)
        s sqlResult = sqlStatement.%Execute()
        s stateType = sqlStatement.%Metadata.statementType
        if (sqlResult.%Message '= "") {
    	    $$$ThrowSqlException(sqlResult.%Message)
        }else {
            return sqlResult.%ROWID
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 调用时可直接将前端所需要的插入字段组成JSON传入后端即可INSERT
    ClassMethod MainInsert()
    {
    	s obj = {}
    	s obj.math = 90
    	s obj.chinese = 90
    	s obj.english = 90
    	#; 模拟前端传进来的json传
    	q ..SaveScore(obj)
    }
    
    ClassMethod SaveScore(pJson As %DynamicObject)
    {
    	#; 直接将json传如即可返回结果
    	s result = ##class(M.Common.Sql).Save(pJson, "M_T.Score")
    	q result
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    IMP>w ##class(M.Score).MainInsert()
    3
    
    • 1
    • 2

    在这里插入图片描述

    更新 UPDATE

    • 与插入INSERT类似前端更新数据,可能只是某一些字段进行更新,所以要根据前端的映射字段找到后端表的属性字段,在组装SQL
    1. 根据映射字段找到属性字段。(同INSERT
    2. 获取到表的属性字段后组装UPDATE语句,这里需要传入ID进行更新。
    ClassMethod Json2SqlUpdate(zJson)
    {
        s data = zJson.data
        s table = zJson.table
        s rowID = zJson.id
        
        s iter = data.%GetIterator()
        s fieldDataStr = ""
        while iter.%GetNext(.key, .value) {
            if ($listvalid(value)){
                if (value = ""){
                    s fmtValue = "NULL"
                }else{
                    s fmtValue = "$LISTFROMSTRING('" _ $lts(value) _ "')"
                }
            }else{
                s fmtValue = $s(value = "" : "NULL" , 1 : "'" _ value _ "'")
            }
    
            s fieldData = key _ " = " _ fmtValue
            s fieldDataStr = $s(fieldDataStr = "" : fieldData, 1 : fieldDataStr _ "," _ fieldData)
        }
        q "UPDATE " _ table _ " SET " _ fieldDataStr _ " WHERE %ID = '" _ rowID _"'"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 把得到的SQL语句执行。(同INSERT
    2. 调用时可直接将前端所需要的更新字段组成JSON传入后端即可UPDATE
    ClassMethod SaveScore(pJson As %DynamicObject)
    {
    	#; 直接将json传如即可返回结果
    	s result = ##class(M.Common.Sql).Save(pJson, "M_T.Score")
    	q result
    }
    
    /// w ##class(M.Score).MainUpdate()
    ClassMethod MainUpdate()
    {
    	s obj = {}
    	s obj.id = 1
    	s obj.math = 10
    	s obj.chinese = 10
    	s obj.english = 10
    	#; 模拟前端传进来的json传,update需要根据ID
    	q ..SaveScore(obj)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    IMP>w ##class(M.Score).MainUpdate()
    1
    
    • 1
    • 2

    在这里插入图片描述

    删除 DELETE

    ClassMethod Json2SqlDelete(zJson)
    {
        s table = zJson.table
        s rowID = zJson.id
        q "DELETE FROM " _ table _ " WHERE %ID = '" _ rowID _ "'"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 删除最简单只需要传入,需要的删除ID即可。
    ClassMethod MainDelete()
    {
    	s obj = {}
    	s obj.id = 2
    	q ..DeleteScore(obj)
    }
    
    ClassMethod DeleteScore(pJson As %DynamicObject)
    {
    	#; 直接将json传如即可返回结果
    	s result = ##class(M.Common.Sql).Delete(pJson, "M_T.Score")
    	q result
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    IMP>w ##class(M.Score).MainDelete()
    2
    
    • 1
    • 2

    在这里插入图片描述

    查询 QUERY

    1. 利用单条数根据ID获取JSON对象的特性,将它转成存储过程,在查询里调用。
    ClassMethod Query(pJson As %Library.DynamicObject, tableName)
    {
        s sqlCode($i(sqlCode)) = " SELECT IMP_Common.Sql_Data(%ID,'" _ tableName _ "')"
        s sqlCode($i(sqlCode)) = " FROM " _ tableName _ ""
        q ##class(IMP.Common.Sql).DynamicSql2Array(.sqlCode)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. SQL进行执行,这里判断如果是JSON对象则直接Push到数组里。
    ClassMethod DynamicSql2Array(ByRef sqlCode) As %DynamicArray
    {
        s ret = []
        s sqlStatement = ##class(%SQL.Statement).%New()
        s sqlStatus = sqlStatement.%Prepare(.sqlCode)
        s sqlResult = sqlStatement.%Execute() 
    
    	$$$ThrowOnError(sqlStatus)
    
        s columns = sqlStatement.%Metadata.columns
        s colCount = sqlResult.%ResultColumnCount
        for {
            q:('sqlResult.%Next())
            s rowData = sqlResult.%GetData(1)
            if (colCount = 1)&&($isobject(rowData)){
    	        #; 如果是json对象则直接添加
                d ret.%Push(rowData)
            }else{
                #; 兼容多列
                s rowData = {}
                for i = 1 : 1 : colCount{
                    s val = sqlResult.%GetData(i)
                    s colName = columns.GetAt(i).colName
                    d rowData.%Set(colName, val)
                }
                d ret.%Push(rowData)
            }
        }
        q ret
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    1. 直接传入表名进行调用,返回给前端表格所需的数据。
    ClassMethod Query(pJson As %Library.DynamicObject, tableName)
    {
        s sqlCode($i(sqlCode)) = " SELECT IMP_Common.Sql_Data(%ID,'" _ tableName _ "')"
        s sqlCode($i(sqlCode)) = " FROM " _ tableName _ ""
        q ..DynamicSql2Array(.sqlCode)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    IMP> d ##class(M.Score).QueryScore({}).%ToJSON()
    [{"id":1,"chinese":"10","english":"10","math":"10"},{"id":3,"chinese":"90","english":"90","math":"90"}]
    
    • 1
    • 2

    总结

    最后我们总结一下调用方法。

    • 查询单条数据
    ##class(M.Common.Sql).Data(pJson.id, "M_T.Score")
    
    • 1
    • 插入或更新
    ##class(M.Common.Sql).Save(pJson, "M_T.Score")
    
    • 1
    • 删除数据
    ##class(M.Common.Sql).Delete(pJson, "M_T.Score")
    
    • 1
    • 查询列表数据
    ##class(M.Common.Sql).Query(pJson, "M_T.Score")
    
    • 1

    综上所述,只要对表建立映射,我们可以不用书写任何一条SQL语句,只输入表名,就可以进行CURD

    回过头看我们的方案是不是有一些类似简单版本的MyBatis


    再次思考

    我们是否可以通过实体类直接来调用如上增删改查的方式,连表名都不用去传参,直接调用实体类就可以直接去执行?

    下面我们结合前端页面来实践一下。

    改造映射类

    我们可以利用$this指定当前的上下文环境的类名,来直接用实体类来调用对应方法

    M.Map增加如下四个方法

    ClassMethod Save(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Save(pJson, tableName)
    }
    
    ClassMethod Query(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Query(pJson, tableName)
    }
    
    ClassMethod Delete(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Delete(pJson, tableName)
    }
    
    ClassMethod Data(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Data(pJson.id, tableName)
    }
    
    ClassMethod GetTableNameByClassName(className)
    {
    	&sql(SELECT SqlQualifiedNameQ into :tableName FROM   %Dictionary.CompiledClass WHERE ID = :className)
    	q tableName
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    查询列表数据

    • 前端

    HTML:

    在这里插入图片描述

    JS:

    在这里插入图片描述

    • 后端
    ClassMethod QueryRaw(pJson As %Library.DynamicObject)
    {
    	q ##class(M.T.Score).Query(pJson)
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    新增与更新与单条数据查询

    • 前端

    HTML:

    在这里插入图片描述

    JS:

    在这里插入图片描述

    在这里插入图片描述

    • 后端
    ClassMethod InsertRaw(pJson As %Library.DynamicObject)
    {
    	q ##class(M.T.Score).Save(pJson)
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    ClassMethod DataRaw(pJson As %Library.DynamicObject)
    {
    	q ##class(M.T.Score).Data(pJson)
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    ClassMethod UpdateRaw(pJson As %Library.DynamicObject)
    {
    	q ##class(M.T.Score).Save(pJson)
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    在这里插入图片描述

    删除

    • 前端

    在这里插入图片描述

    • 后端
    ClassMethod DeleteRaw(pJson As %Library.DynamicObject)
    {
    	q ##class(M.T.Score).Delete(pJson)
    }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    在这里插入图片描述

    总结

    最后我们再次总结一下调用方法。

    • 查询单条数据
    ##class(实体类名).Data(pJson.id)
    
    • 1
    • 插入或更新
    ##class(实体类名).Save(pJson)
    
    • 1
    • 删除数据
    ##class(实体类名).Delete(pJson)
    
    • 1
    • 查询列表数据
    ##class(实体类名).Query(pJson)
    
    • 1

    最后

    综上所诉:我们只需要对实体表,增加别名映射,继承M.Map映射类。就可以在也不用写,解析,组装,写SQL了。

    适用情况:

    • 适合不复杂的表操作,查询。
    • 效率上也在可接受范围之内。

    最后思考

    1. 查询时,需要WHERE查询时,根据表单筛选进行WHERESQL语句自动编写对照呢,自动生成筛选条件?
    2. 根据映射做字段的表单验证?

    理论上:都是可行的,留给大家思考完善。

    参考

    • 此方案由云海宝云工通用SQL基础上演化而来。

    分享,开源,利他,创造价值,分享学习,一起成长,相伴前行。

    Github

    https://github.com/yaoxin521123/IRIS-MAP-SQL.git
    
    • 1
    https://github.com/yaoxin521123/IRIS-TOOL.git
    
    • 1

    完整代码

    • M.Person
    Class M.Person Extends %RegisteredObject
    {
    
    ClassMethod Insert(pJson As %Library.DynamicObject)
    {
    	s name = pJson.name
    	s age = pJson.age
    	s no = pJson.no
    	&sql(insert into M_T.Person (MT_Name, MT_Age, MT_No) values(:name, :age, :no))
    	q SQLCODE
    }
    
    ClassMethod Update(pJson As %Library.DynamicObject)
    {
    	s id = pJson.id
    	s name = pJson.name
    	s age = pJson.age
    	s no = pJson.no
    	&sql(update M_T.Person set MT_Name = :name, MT_Age = :age, MT_No = :no where %ID = :id)
    	q SQLCODE
    }
    
    ClassMethod Delete(pJson As %Library.DynamicObject)
    {
    	s id = pJson.id
    	&sql(delete M_T.Person where ID = :id)
    	q SQLCODE
    }
    
    /// w ##class(M.Sql).QueryBySql().%ToJSON()
    ClassMethod QueryBySql(pJson As %Library.DynamicObject = {{}})
    {
    	s name = pJson.name
    	s sql = "SELECT ID,MT_Name, MT_Age, MT_No FROM M_T.Person "
    	if (name '= "") {
    		s sql = sql _ " where MT_Name = '" _ name _"'"
    	}
    	s mStatement = ##class(%SQL.Statement).%New()
    	s sc = mStatement.%Prepare(.sql)
    	s rs = mStatement.%Execute()
    	
    	s array = []
    	while rs.%Next() {
    		s name = rs.%Get("MT_Name")
    		s age = rs.%Get("MT_Age")
    		s no = rs.%Get("MT_No")
    		s id = rs.%Get("ID")
    		s obj = {}
    		s obj.name = name
    		s obj.age = age
    		s obj.no = no
    		s obj.id = id
    		d array.%Push(obj)
    	}
    	q array
    }
    
    ClassMethod GetDataById(pJson As %Library.DynamicObject = {{}})
    {
    	s id = pJson.id
    	s data = ^M.T.PersonD(id)
    	s name = $lg(data, 2)
    	s age = $lg(data, 3)
    	s no = $lg(data, 4)
    	s obj = {}
    	s obj.name = name
    	s obj.age = age
    	s obj.no = no
    	s obj.id = id
    	q obj
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • M.Score
    Class M.Score Extends %RegisteredObject
    {
    
    ClassMethod Insert()
    {
    	&sql(insert into M_T.Score (MT_Math, MT_Chinese, MT_English) values(:name, :age, :no))
    	q SQLCODE
    }
    
    /// w ##class(M.Score).QueryScoreById({"id" : 1}).%ToJSON()
    ClassMethod QueryScoreById(pJson As %Library.DynamicObject)
    {
    	#; 只需要传入对应ID与表明
        q ##class(M.Common.Sql).Data(pJson.id, "M_T.Score")
    }
    
    /// w ##class(M.Score).MainInsert()
    ClassMethod MainInsert()
    {
    	s obj = {}
    	s obj.math = 90
    	s obj.chinese = 90
    	s obj.english = 90
    	#; 模拟前端传进来的json传
    	q ..SaveScore(obj)
    }
    
    ClassMethod SaveScore(pJson As %DynamicObject)
    {
    	#; 直接将json传如即可返回结果
    	s result = ##class(M.Common.Sql).Save(pJson, "M_T.Score")
    	q result
    }
    
    /// w ##class(M.Score).MainUpdate()
    ClassMethod MainUpdate()
    {
    	s obj = {}
    	s obj.id = 1
    	s obj.math = 10
    	s obj.chinese = 10
    	s obj.english = 10
    	#; 模拟前端传进来的json传,update需要根据ID
    	q ..SaveScore(obj)
    }
    
    /// w ##class(M.Score).MainDelete()
    ClassMethod MainDelete()
    {
    	s obj = {}
    	s obj.id = 2
    	q ..DeleteScore(obj)
    }
    
    ClassMethod DeleteScore(pJson As %DynamicObject)
    {
    	#; 直接将json传如即可返回结果
    	s result = ##class(M.Common.Sql).Delete(pJson, "M_T.Score")
    	q result
    }
    
    /// d ##class(M.Score).QueryScore({}).%ToJSON()
    ClassMethod QueryScore(pJson As %Library.DynamicObject)
    {
        q ##class(M.Common.Sql).Query(pJson, "M_T.Score")
    }
    
    /// w ##class(M.Score).InsertRaw()
    ClassMethod InsertRaw(pJson As %Library.DynamicObject)
    {
    #;	s obj = {}
    #;	s obj.math = 90
    #;	s obj.chinese = 80
    #;	s obj.english = 70
    	q ##class(M.T.Score).Save(pJson)
    }
    
    /// w ##class(M.Score).UpdateRaw()
    ClassMethod UpdateRaw(pJson As %Library.DynamicObject)
    {
    #;	s obj = {}
    #;	s obj.id = 5
    #;	s obj.math = 20
    #;	s obj.chinese = 20
    #;	s obj.english = 20
    	q ##class(M.T.Score).Save(pJson)
    }
    
    /// w ##class(M.Score).DeleteRaw()
    ClassMethod DeleteRaw(pJson As %Library.DynamicObject)
    {
    #;	s obj = {}
    #;	s obj.id = 4
    
    	q ##class(M.T.Score).Delete(pJson)
    }
    
    /// w ##class(M.Score).DataRaw().%ToJSON()
    ClassMethod DataRaw(pJson As %Library.DynamicObject)
    {
    #;	s obj = {}
    #;	s obj.id = 5
    
    	q ##class(M.T.Score).Data(pJson)
    }
    
    /// w ##class(M.Score).QueryRaw().%ToJSON()
    ClassMethod QueryRaw(pJson As %Library.DynamicObject)
    {
    #;	s obj = {}
    
    	q ##class(M.T.Score).Query(pJson)
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • M.Map
    Class M.Map Extends %RegisteredObject [ Abstract ]
    {
    
    /// desc:映射字段
    /// 没有写到%code里的代码是直接判断来执行的
    /// %class 是 %Dictionary.ClassDefinition 的对象
    /// %code 是 %Stream.MethodGenerator 的对象
    /// w ##class(CT.IMP.SysRole).MapField().%ToJSON()
    ClassMethod MapField() [ CodeMode = objectgenerator ]
    {
    	#; 不是抽象类直接退出
    	if '%class.Abstract {
    
    		#; 获取类名,如果类不声明关键字 类型为 ClassType = persistent 则退出
    		s className = %class.Name
    		q:(%class.ClassType '= "persistent") $$$OK
    		
    		d %code.WriteLine(" s obj = ..QueryFieldMap("""_ className _""")") 
    	    d %code.WriteLine(" q obj")   
    	}
        q $$$OK
    }
    
    /// desc:查询映射字段
    /// w ##class(M.Map).QueryFieldMap("CT_IMP.SysRole").%ToJSON()
    /// w ##class(M.Map).QueryFieldMap("M.T.Score").%ToJSON()
    ClassMethod QueryFieldMap(className)
    {
    	#; 包名
    	s schema = $p(className, ".", 1, * - 1)
    	
    	#; 表名
    	s table = $p(className, ".", *)
    	
    	#; 将包名替换为带下划线的架构名
    	s schema = $replace(schema, ".", "_")
    
    	s obj = ##class(%Library.DynamicObject).%New()  
    	s sql = "SELECT * FROM INFORMATION_SCHEMA.Columns where TABLE_NAME  = '"_table _"' AND TABLE_SCHEMA = '"_schema_"'"
    	s mStatement = ##class(%SQL.Statement).%New()
    	s status = mStatement.%Prepare(.sql)
    	$$$ThrowOnError(status)
    	s result = mStatement.%Execute()
    	
    	while result.%Next() {
    		
    		#; 取字段名称
    		s fieldName =  result.%Get("COLUMN_NAME")
    		
    		#; 取字别名
    		s propertyName = $replace(fieldName, "_", "")
    		s alies = $g(^oddDEF(className, "a",propertyName, 58))
    
    		#; 别名不为空取别名,否则取字段名
    		s key = $s(alies '= "" : alies, 1 : fieldName)
    
    		d obj.%Set(key, fieldName)
    	}
    
        q obj
    }
    
    ClassMethod Save(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Save(pJson, tableName)
    }
    
    ClassMethod Query(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Query(pJson, tableName)
    }
    
    ClassMethod Delete(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Delete(pJson, tableName)
    }
    
    ClassMethod Data(pJson As %Library.DynamicObject)
    {
    	s tableName = ..GetTableNameByClassName($this)
    	q ##class(M.Common.Sql).Data(pJson.id, tableName)
    }
    
    ClassMethod GetTableNameByClassName(className)
    {
    	&sql(SELECT SqlQualifiedNameQ into :tableName FROM   %Dictionary.CompiledClass WHERE ID = :className)
    	q tableName
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • M.Common.Sql
    Class M.Common.Sql Extends %RegisteredObject
    {
    
    ClassMethod DynamicSql2Array(ByRef sqlCode) As %DynamicArray
    {
        s ret = []
        s sqlStatement = ##class(%SQL.Statement).%New()
        s sqlStatus = sqlStatement.%Prepare(.sqlCode)
        s sqlResult = sqlStatement.%Execute() 
    
    	$$$ThrowOnError(sqlStatus)
    	
        s columns = sqlStatement.%Metadata.columns
        s colCount = sqlResult.%ResultColumnCount
        for {
            q:('sqlResult.%Next())
            s rowData = sqlResult.%GetData(1)
            if (colCount = 1)&&($isobject(rowData)){
                d ret.%Push(rowData)
            }else{
                #; 兼容多列
                s rowData = {}
                for i = 1 : 1 : colCount{
                    s val = sqlResult.%GetData(i)
                    s colName = columns.GetAt(i).colName
                    d rowData.%Set(colName, val)
                }
                d ret.%Push(rowData)
            }
        }
        q ret
    }
    
    ClassMethod Json2Sql(zJson)
    {
        s type = zJson.type
        q $case(type,
                    "UPDATE": ..Json2SqlUpdate(zJson),
                    "INSERT": ..Json2SqlInsert(zJson),
                    "DELETE": ..Json2SqlDelete(zJson),
                    :""
                    )
    }
    
    ///  w ##class(M.Common.Sql).Json2SqlInsert({"type":"INSERT","table":"M_T.Score","id":"","data":{"MT_Math":90,"MT_Chinese":90,"MT_English":90}}).%ToJSON()
    ClassMethod Json2SqlInsert(zJson)
    {
        s data = zJson.data
        s table = zJson.table
        
        s iter = data.%GetIterator()
        s nameStr = ""
        s dataStr = ""
        while iter.%GetNext(.key, .value) {
            s nameStr = $s(nameStr = "" : key, 1 : nameStr _ "," _ key)
            if ($listvalid(value)){
                if (value = ""){
                    s fmtValue = "NULL"
                }else{
                    s fmtValue = "$LISTFROMSTRING('" _ $lts(value) _ "')"
                }
            }else{
                s fmtValue = $s(value = "" : "NULL" , 1 : "'" _ value _ "'")
            }
            s dataStr = $s(dataStr = "" : fmtValue, 1 : dataStr _ "," _ fmtValue)
        }
        q "INSERT INTO " _ table _ "(" _ nameStr _ ") VALUES (" _ dataStr _ ")"
    }
    
    ClassMethod Json2SqlUpdate(zJson)
    {
        s data = zJson.data
        s table = zJson.table
        s rowID = zJson.id
        
        s iter = data.%GetIterator()
        s fieldDataStr = ""
        while iter.%GetNext(.key, .value) {
            if ($listvalid(value)){
                if (value = ""){
                    s fmtValue = "NULL"
                }else{
                    s fmtValue = "$LISTFROMSTRING('" _ $lts(value) _ "')"
                }
            }else{
                s fmtValue = $s(value = "" : "NULL" , 1 : "'" _ value _ "'")
            }
    
            s fieldData = key _ " = " _ fmtValue
            s fieldDataStr = $s(fieldDataStr = "" : fieldData, 1 : fieldDataStr _ "," _ fieldData)
        }
        q "UPDATE " _ table _ " SET " _ fieldDataStr _ " WHERE %ID = '" _ rowID _"'"
    }
    
    ClassMethod Json2SqlDelete(zJson)
    {
        s table = zJson.table
        s rowID = zJson.id
        q "DELETE FROM " _ table _ " WHERE %ID = '" _ rowID _ "'"
    }
    
    ClassMethod XJson2Sql(zJson)
    {
        q ..XSQL(..Json2Sql(zJson))
    }
    
    ClassMethod XSQL(sqlStr)
    {
    	#define ThrowSqlException(%str)  throw:((SQLCODE '= 0)&&(SQLCODE '= 100)) ##class(%Exception.SystemException).%New("SQL错误", SQLCODE, , %str _ ":" _ " SQLCODE:"_ SQLCODE  _ " %msg:"_ $g(%msg))
        s sqlStatement = ##class(%SQL.Statement).%New()
        s sqlStatus = sqlStatement.%Prepare(sqlStr)
        $$$ThrowOnError(sqlStatus)
        s sqlResult = sqlStatement.%Execute()
        s stateType = sqlStatement.%Metadata.statementType
        if (sqlResult.%Message '= "") {
    	    $$$ThrowSqlException(sqlResult.%Message)
        }else {
            return sqlResult.%ROWID
        }
    }
    
    ClassMethod MapJson2SqlFields(map As %DynamicObject, json As %DynamicObject) As %DynamicObject
    {
        #dim ret as %DynamicObject = {}
        q:(map.%ToJSON() = "{}") json
        
        s iter = json.%GetIterator()
        while iter.%GetNext(.key, .value) {
            continue:(map.%GetTypeOf(key) = "unassigned") 
            s newKey = map.%Get(key)   
            d ret.%Set(newKey, value)       
        } 
        
        q ret
    }
    
    ClassMethod MapJson2SelectInto(mapJson) As %List
    {
        #dim ret as %List = ""
        s iter = mapJson.%GetIterator()
        s mapList = ""
        s fieldList = "" 
        while iter.%GetNext(.mapKey, .sqlField) {
            s fieldList = fieldList _ $lb(sqlField)
            s mapList = mapList _ $lb(":" _ mapKey)
        }
        
        q $lb($lts(fieldList), $lts(mapList))
    }
    
    ClassMethod Save(pJson As %Library.DynamicObject, tableName As %String) As %Integer
    {
        s id = pJson.id
        
        #; 将表名替换为类名
        s className = $replace(tableName, "_", ".")
    	
    	 #; 获取对照
        s dataMap = $classmethod(className, "MapField")  
        s result =  ..XJson2Sql({
            "type": ($s(id '= "" : "UPDATE" , 1 : "INSERT")),
            "table": (tableName),
            "id": (id),
            "data": (..MapJson2SqlFields(dataMap, pJson))
        })
        q result
    }
    
    ClassMethod Delete(pJson As %Library.DynamicObject, tableName As %String) As %Integer
    {
    	s id = pJson.id
    	q:(id = "") $$$OK
    	q ..XJson2Sql({
    	    "type": "DELETE",
    	    "table": (tableName),
    	    "id": (id)
    	})
    }
    
    ClassMethod Data(id As %Integer, tableName As %String) As %DynamicObject [ SqlProc ]
    {
    	#; 获取类名
    	s className = $replace(tableName, "_", ".")
    	
    	#; 获取映射
    	s mapJson = $classmethod(className, "MapField")
    
    	#; 组装查询SQL字符串
    	s str = "json_object("
    	s iter = mapJson.%GetIterator()
    	while iter.%GetNext(.key, .value) {
    		continue:(mapJson.%GetTypeOf(key) = "unassigned") 
    		s str = str _ "'" _key _ "'" _ ":" _ value _ ","
    
    	} 
    	
    	#; 删除最后一个逗号
    	s str = $e(str, 1, * - 1)
    	s str = str _ ")  as json "
    	s sql = "SELECT  " _ str _ " FROM " _ tableName _ " where %ID = ?"
    	
    	#; 执行查询
    	s mStatement = ##class(%SQL.Statement).%New()
    	s status = mStatement.%Prepare(.sql)
    	s result = mStatement.%Execute(id)
    	
    	#; 获取表的数据
    	while result.%Next() {
    		s jsonStr = result.%Get("json")
    		s json = {}.%FromJSON(jsonStr)
    	}
    	q json
    }
    
    ClassMethod Query(pJson As %Library.DynamicObject, tableName)
    {
        s sqlCode($i(sqlCode)) = " SELECT IMP_Common.Sql_Data(%ID,'" _ tableName _ "')"
        s sqlCode($i(sqlCode)) = " FROM " _ tableName _ ""
        q ..DynamicSql2Array(.sqlCode)
    }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • M.T.Person
    Class M.T.Person Extends %Persistent [ SqlTableName = Person ]
    {
    
    Property MTName As %String [ SqlFieldName = MT_Name ];
    
    Property MTAge As %Integer [ SqlFieldName = MT_Age ];
    
    Property MTNo As %String [ SqlFieldName = MT_No ];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • M.T.Score
    Class M.T.Score Extends (%Persistent, M.Map) [ ClassType = persistent, SqlRowIdName = id, SqlTableName = Score ]
    {
    
    Property MTMath As %String [ Aliases = {math}, SqlFieldName = MT_Math ];
    
    Property MTChinese As %String [ Aliases = {chinese}, SqlFieldName = MT_Chinese ];
    
    Property MTEnglish As %String [ Aliases = {english}, SqlFieldName = MT_English ];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    百战RHCE(第五十一战:运维工程师必会技-Ansible学习6-编写和执行Playbook)
    【C++】如何修改set的值
    Yapi浏览器插件
    大佬们有没有办法把这个json变成sql db或者df?
    【数据结构与算法分析】0基础带你学数据结构与算法分析08--二叉查找树 (BST)
    算法——顺序表(1)
    什么是全真互联网?腾讯版Web3元宇宙?
    ES入门十:关系模型的实现:嵌套类型和父子文档
    【python】OpenCV—Rectangle, Circle, Selective Search(1.2)
    FPGA面试题
  • 原文地址:https://blog.csdn.net/yaoxin521123/article/details/127995311