<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          開源SPL,ORM的終結(jié)者?

          共 6816字,需瀏覽 14分鐘

           ·

          2022-03-02 18:39

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????


          來源丨Java知音


          業(yè)務(wù)邏輯經(jīng)常包含較復(fù)雜的流程和計算,同時涉及數(shù)據(jù)庫的讀寫。由于授權(quán)麻煩、影響數(shù)據(jù)庫安全、無法遷移、技術(shù)要求高、編寫困難等原因,很多場景不適合用存儲過程實現(xiàn)業(yè)務(wù)邏輯。因為不擅長復(fù)雜的流程處理,SQL也不適合單獨(dú)實現(xiàn)業(yè)務(wù)邏輯,必須與JAVA等高級語言配合才行。但SQL和高級語言的語法風(fēng)格迥然不同,數(shù)據(jù)結(jié)構(gòu)差異巨大,導(dǎo)致兩者難以配合,開發(fā)效率始終無法提高。在這種情況下,ORM適時而生。
          ORM是一種將結(jié)構(gòu)化數(shù)據(jù)(表/記錄)映射為高級語言的對象的技術(shù),這樣就可以用統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)和語法風(fēng)格實現(xiàn)業(yè)務(wù)邏輯其根本目標(biāo)還是提高開發(fā)效率。常見的ORM技術(shù)有Hibernate、QueryDSL、JOOQ等。
          在數(shù)據(jù)結(jié)構(gòu)和語法風(fēng)格的統(tǒng)一方面,ORM表現(xiàn)優(yōu)秀,已經(jīng)在大量項目中得到廣泛應(yīng)用。但ORM仍有很多不足,主要表現(xiàn)在:缺乏專業(yè)的結(jié)構(gòu)化數(shù)據(jù)類型,集合運(yùn)算不夠方便,讀寫數(shù)據(jù)庫時代碼繁瑣,不支持熱部署,庫函數(shù)不夠豐富,復(fù)雜計算難以實現(xiàn)。ORM的這些缺點(diǎn)導(dǎo)致業(yè)務(wù)邏輯的開發(fā)效率沒有明顯提升,有時甚至大幅降低。
          作為JAVA下開源的結(jié)構(gòu)化數(shù)據(jù)處理類庫,SPL可以解決ORM期望目標(biāo),甚至有更好的表現(xiàn)。

          SPL用統(tǒng)一數(shù)據(jù)結(jié)構(gòu)和語法風(fēng)格實現(xiàn)業(yè)務(wù)邏輯

          比如一個常見的業(yè)務(wù)邏輯:根據(jù)規(guī)則計算出獎金,向數(shù)據(jù)庫插入包含獎金字段的記錄??捎孟旅娴腟PL代碼實現(xiàn):

          ABC
          1=db=connect@e("dbName")
          /連接數(shù)據(jù)庫,開啟事務(wù)
          2=db.query@1("select   sum(Amount)  from sales where
            sellerID=? and year(OrderDate)=? and month(OrderDate)=?",
            p_SellerID,year(now()),month(now()))

          /查詢當(dāng)月銷售額
          3=if(A2>=10000   :200, A2<10000 && A2>=2000 :100, 0)
          /本月累計獎金
          4=p_Amount*0.05
          /本單固定獎金
          5=BONUS=A3+A4
          /總獎金
          6=create(ORDERID,CLIENT,SELLERID,AMOUNT,BONUS,ORDERDATE)
          /創(chuàng)建訂單的數(shù)據(jù)結(jié)構(gòu)
          7=A6.record([p_OrderID,p_Client,p_SellerID,p_Amount,BONUS,
            date(now())])

          /生成一條訂單記錄
          8>db.update@ik(A7,sales;ORDERID)
          /嘗試寫入庫表
          9=db.error()
          /入庫結(jié)果
          10if A9==0>A1.commit()/成功,則提交事務(wù)
          11Else>A1.rollback()/失敗,則回滾事務(wù)
          12>db.close()
          /關(guān)閉數(shù)據(jù)庫連接
          13return   A9
          /返回入庫結(jié)果

          上面的SPL代碼使用統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)、語法、函數(shù),就可以完成整個業(yè)務(wù)邏輯的開發(fā),包括數(shù)據(jù)庫讀寫、事務(wù)處理、流程處理、數(shù)據(jù)計算。

          JAVA代碼本身不包含業(yè)務(wù)邏輯,通過JDBC驅(qū)動引用上面的SPL腳本,就可以實現(xiàn)業(yè)務(wù)邏輯。
          //省略參數(shù)的獲取過程Class.forName("com.esproc.jdbc.InternalDriver");Connection conn =DriverManager.getConnection("jdbc:esproc:local://");CallableStatement statement = conn.prepareCall("{call InsertSales(?, ?,?,?)}");statement.setObject(1, d_OrderID);statement.setObject(2, d_Client);statement.setObject(3, d_SellerID);statement.setObject(4, d_Amount);statement.execute();...

          JAVA調(diào)用SPL的形式與調(diào)用存儲過程相同,且無須數(shù)據(jù)庫管理員授權(quán),不影響數(shù)據(jù)庫安全,便于遷移,方便調(diào)試,處理能力更強(qiáng),代碼更簡單。


          SPL提供了專業(yè)的結(jié)構(gòu)化數(shù)據(jù)對象,具備完整的內(nèi)外數(shù)據(jù)交換能力和流程控制能力。

          結(jié)構(gòu)化數(shù)據(jù)對象

          業(yè)務(wù)邏輯圍繞結(jié)構(gòu)化數(shù)據(jù)對象展開,SQL、ORM、SPL都內(nèi)置專業(yè)的結(jié)構(gòu)化數(shù)據(jù)對象,并據(jù)此提供了各自的結(jié)構(gòu)化數(shù)據(jù)計算函數(shù)。類似ORM的實體/List<實體>,SPL的結(jié)構(gòu)化數(shù)據(jù)對象是記錄/序表。
          取記錄的字段值:=r.AMOUNT*0.05
          修改記錄的字段值:=r.AMOUNT= T.AMOUNT*1.05
          序表取一列:T.(AMOUNT)
          序表追加記錄:T.insert(0,31,"APPL",10,2400.4)
          基于序表,SPL提供了豐富的SQL式計算函數(shù)。
          過濾:T.select(Amount>1000 && Amount<=3000 && like(Client,"*bro*"))
          排序:T.sort(-Client,Amount)
          去重:T.id(Client)
          匯總:T.max(Amount)
          分組匯總后過濾:T.groups(year(OrderDate),Client; avg(Amount):amt).select(amt>2000)
          關(guān)聯(lián):join(Orders:o,SellerId ; Employees:e,EId).groups(e.Dept; sum(o.Amount))
          交集:T1.id(Client) ^ T2.id(Client)
          TopN:T.top(-3;Amount)
          分組topN:T.groups(Client;top(3,Amount))
          此外,SPL還提供了字符串、日期、數(shù)學(xué)等多種函數(shù),充分滿足業(yè)務(wù)邏輯中的計算需求。

          內(nèi)外數(shù)據(jù)交換能力

          將外部數(shù)據(jù)庫的記錄讀為內(nèi)部結(jié)構(gòu)化數(shù)據(jù)對象,ORM主要通過主鍵查詢、HQL查詢、SQL查詢、鏈?zhǔn)骄幊痰确绞?。類似地,SPL提供了query函數(shù)執(zhí)行SQL的方式。

          取單條記錄:

          =r=db.query("select * from sales where orderid=?",201)

          取序表(記錄集合):

          =T=db.query("select * from salesR where SellerID=?",10)
          為了增強(qiáng)可移植性,SPL提供了通用SQL,使用sqltranslate函數(shù)可將通用SQL轉(zhuǎn)為主流方言SQL,仍然通過query函數(shù)執(zhí)行。這不是本文重點(diǎn),不展開說了。
          將內(nèi)部結(jié)構(gòu)化數(shù)據(jù)對象持久化到數(shù)據(jù)庫,ORM主要通過save(新增的實體)、update(修改的實體)、delete(刪除的實體)等方式。類似地,SPL使用update函數(shù)。

          比如,原序表為 T,經(jīng)過增刪改之后的序表為 NT, 將變化結(jié)果持久化到數(shù)據(jù)庫:

          =db.update(NT:T,sales;ORDERID)

          流程控制能力

          業(yè)務(wù)邏輯的難點(diǎn)在于復(fù)雜的流程控制(判斷和循環(huán))。SQL缺乏流程控制能力,ORM把數(shù)據(jù)庫表映射為JAVA對象,主要目的就是為了更方便地利用JAVA的流程控制能力。類似JAVA,SPL具備完整的流程控制能力。
          分支判斷語句:

          AB
          2
          3if T.AMOUNT>10000=T.BONUS=T.AMOUNT*0.05
          4else if   T.AMOUNT>=5000 && T.AMOUNT<10000=T.BONUS=T.AMOUNT*0.03
          5else if   T.AMOUNT>=2000 && T.AMOUNT<5000=T.BONUS=T.AMOUNT*0.02

          循環(huán)語句:


          AB
          1=db=connect("db")
          2=T=db.query@x("select   * from sales where SellerID=? order by OrderDate",9)
          3for T=A3.BONUS=A3.BONUS+A3.AMOUNT*0.01
          4
          =A3.CLIENT=CONCAT(LEFT(A3.CLIENT,4),   "co.,ltd.")
          5
           …

          與Java的循環(huán)類似,SPL還可用break關(guān)鍵字跳出(中斷)當(dāng)前循環(huán)體,或用next關(guān)鍵字跳過(忽略)本輪循環(huán),不展開說了。


          SPL超越ORM獲得更高的開發(fā)效率

          SPL不僅能用統(tǒng)一的數(shù)據(jù)結(jié)構(gòu)和語法風(fēng)格實現(xiàn)業(yè)務(wù)邏輯,還能夠達(dá)到ORM的根本目標(biāo),顯著提高業(yè)務(wù)邏輯的開發(fā)效率。

          更多計算函數(shù)

          ORM的計算函數(shù)不足,很多功能都無法實現(xiàn),或需要編寫冗長的代碼。SPL提供了更多的計算函數(shù),可直接實現(xiàn)這些功能,代碼量大幅縮短。

          比如,時間類函數(shù),日期增減:elapse("2020-02-27",5)  //返回2020-03-03

          星期幾:day@w("2020-02-27")   //返回5,即星期6

          N個工作日之后的日期:workday(date("2022-01-01"),25)   //返回2022-02-04

          字符串類函數(shù),判斷是否全為數(shù)字:isdigit("12345")    //返回true

          取子串前面的字符串:substr@l("abCDcdef","cd")      //返回abCD

          按豎線拆成字符串?dāng)?shù)組:"aa|bb|cc".split("|")     //返回["aa","bb","cc"]
          SPL還支持年份增減、求年中第幾天、求季度、按正則表達(dá)式拆分字符串、拆出SQL的where或select部分、拆出單詞、按標(biāo)記拆HTML等功能,數(shù)量較多,不再贅述。

          更方便的集合運(yùn)算

          對結(jié)構(gòu)化數(shù)據(jù)對象(實體集合)進(jìn)行集合運(yùn)算時,ORM有兩種方法:循環(huán)語句+硬編碼,Stream等Lambda表達(dá)式+集合函數(shù)。前者代碼量顯然巨大,后者似乎可以少寫代碼,但因為編譯型Lambda表達(dá)式繁瑣、集合運(yùn)算函數(shù)少且功能弱等原因,導(dǎo)致大多數(shù)運(yùn)算都要輔以硬編碼。比如簡單的分組匯總,就要用到groupingBy、Collectors、summarizingDouble、DoubleSummaryStatistics等多個類和方法。
          SPL提供了簡潔易懂的解釋型Lambda語法,以及數(shù)量眾多的集合函數(shù),可以方便地進(jìn)行集合運(yùn)算。

          比如,批量修改記錄:T.run(BONUS+AMOUNT*0.01: AMOUNT, concat(left(CLIENT,4), "co.,ltd."): CLIENT)

          過濾:T.select(Amount>1000 && Amount<=3000)

          對有序序表按二分法進(jìn)行過濾:T.select@b(Amount>1000 && Amount<=3000)

          分組匯總:T.groups(Client;sum(Amount))

          有序分組(相鄰且字段值相同的記錄分為一組):T.groups@b(Client;sum(Amount))

          涉及跨行的集合運(yùn)算,通常都有一定的難度,比如比上期和同期比。ORM沒有為跨行運(yùn)算做優(yōu)化,代碼通常很繁瑣。SPL使用"字段[相對位置]"引用跨行的數(shù)據(jù),可顯著簡化代碼,還可以自動處理數(shù)組越界等特殊情況。比如,追加一個計算列rate,計算每條訂單的金額增長率:

          =T.derive(AMOUNT/AMOUNT[-1]-1: rate)
          靈活運(yùn)用SPL的Lambda語法和集合函數(shù),可大幅簡化復(fù)雜的集合計算。比如,在各部門找出比本部門平均年齡小的員工:

          A
          1…//省略序表Employees的生成過程
          2=Employees.group(DEPT;   (a=~.avg(age(BIRTHDAY)),~.select(age(BIRTHDAY)<a)):YOUNG)
          3=A2.conj(YOUNG)

          計算某支股票最長的連續(xù)上漲天數(shù):


          A
          1…//省略序表AAPL的生成過程
          2=a=0,AAPL.max(a=if(price>price[-1],a+1,0))


          更專業(yè)的結(jié)構(gòu)化數(shù)據(jù)類型

          ORM的結(jié)構(gòu)化數(shù)據(jù)類型是實體/List<實體>,通用性較強(qiáng),但專業(yè)性不足,很多常用的訪問方法都不支持,比如按字段名取某一個或某幾個列。SPL的結(jié)構(gòu)化數(shù)據(jù)類型是記錄和序表,更加專業(yè),功能也更強(qiáng),常見的訪問方法都支持。

          比如,在序表T的基礎(chǔ)上,按字段名取一列,返回簡單集合:T.(AMOUNT)。

          取幾列,返回集合的集合:T.([CLIENT,AMOUNT])

          取幾列,返回新序表:T.new(CLIENT,AMOUNT)

          按序號訪問通常難度較大,序表天然有序,很容易處理此類問題。比如,按列號取幾列,返回新序表:T.new(#2,#4)

          按序號倒數(shù)取記錄:T.m(-2)

          按序號取某幾條記錄形成序表:T([3,4,5])

          按范圍取記錄形成序表:T(to(3,5))

          先按字段取再按記錄序號?。篢.(AMOUNT)(2);等價于先按記錄序號取再按字段?。篢(2).AMOUNT
          除此之外,SPL還有很多基于序表的高級功能,如TopN、蛇形取值、有序關(guān)聯(lián)等。

          解釋執(zhí)行和熱部署

          業(yè)務(wù)邏輯數(shù)量多,復(fù)雜度高,變化是常態(tài)。良好的系統(tǒng)構(gòu)架,應(yīng)該有能力應(yīng)對變化的業(yè)務(wù)邏輯。ORM的本質(zhì)是JAVA代碼,需要先編譯再執(zhí)行,一般都要停機(jī)才能部署,應(yīng)對變化的業(yè)務(wù)邏輯時非常繁瑣。
          SPL是基于JAVA的解釋型語言,無須編譯就能執(zhí)行,腳本修改后立即生效,支持不停機(jī)的熱部署,適合應(yīng)對變化的業(yè)務(wù)邏輯。

          更方便的數(shù)據(jù)庫讀寫方法

          大量的業(yè)務(wù)邏輯要讀寫批量記錄,這種情況下ORM只能循環(huán)ArrayList,并單獨(dú)處理每條記錄,代碼冗長繁瑣。遇到既有新增,又有修改和刪除的批量寫庫的情況,ORM的代碼就更復(fù)雜了。
          基于序表,SPL提供了更方便的方法讀寫批量記錄,可大幅簡化代碼。比如批量修改記錄:

          AB
          1
          2=T=db.query("select   * from salesR where SellerID=?",10)/批量查詢,序表 T
          3=NT=T.derive()/復(fù)制出新序表 NT
          4=NT.field("SELLERID",9)/批量修改
          5=db.update(NT:T,sales;ORDERID)/持久化到數(shù)據(jù)庫

          上面代碼中,函數(shù)update實現(xiàn)批量修改,無須繁瑣的循環(huán)語句。函數(shù)update經(jīng)過精心設(shè)計,可以統(tǒng)一處理多種批量寫庫方法,遇到既有新增,又有修改和刪除的批量寫庫的情況,SPL的優(yōu)勢更加明顯。


          AB
          1
          2=T=db.query("select   * from salesR where SellerID=?",10)/查出一批記錄
          3=NT=T.derive()/復(fù)制出新序表
          4=NT.delete(NT.select(ORDERID==209   || ORDERID==208))/批量刪除
          5=NT.field("SELLERID",9)/批量修改
          6=NT.record([220,"BTCH",9,5200,100,date("2022-01-02"),
            221,"BTCH",9,4700,200,date("2022-01-03")])
          /批量追加
          7=db.update(NT:T,salesR;ORDERID)/持久化到數(shù)據(jù)庫

          與ORM相比,SPL是專業(yè)的結(jié)構(gòu)化數(shù)據(jù)處理語言,數(shù)據(jù)對象更強(qiáng)大,語法更靈活,函數(shù)更豐富,可以更容易地進(jìn)行數(shù)據(jù)庫讀寫,可以簡化復(fù)雜的流程處理和數(shù)據(jù)計算,可以真正提高業(yè)務(wù)邏輯的開發(fā)效率。

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 34
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品国产一级A片黄毛网站 | 国产日比视频 | 亚洲熟逼 | 青青草逼 | 91这里只有精品 |