Spring-data-jpa中非常簡單的查詢介面方式與CUBA相結合,簡化CUBA開發人員操作數據的方法,能有效提升代碼質量和交付速度 ...
原文鏈接:https://www.cuba-platform.com/blog/spring-query-interfaces-in-cuba
翻譯:CUBA China
CUBA-Platform 官網 : https://www.cuba-platform.com
CUBA China 官網 : http://cuba-platform.cn
根本原因
開發人員通常不喜歡改變他們編碼的習慣。當我剛開始接觸 CUBA 的時候,發現不需要學很多新的東西,創建應用程式的過程也是非常順利的。但是其中有一樣是需要重新學習的,那就是如何使用數據。
在Spring框架中,有好幾個庫可以用來處理數據,其中最流行的一個就是 spring-data-jpa,使用這個庫可以使開發人員在很多情況下避免編寫SQL或者JPQL。只需要創建一個介面類,然後在介面中創建 帶有特殊名稱 的方法,Spring會自動幫你創建和執行查詢語句。
比如,這裡有一個介面,其中有個方法是數數有多少客戶是同一個姓的:
可以直接將這個介面註入到service中,然後就可以在需要的地方調用這個方法了(註意,不需要寫實現類)。
CUBA提供了很多開箱即用的數據操控方法,比如載入實體的部分屬性以及成熟的數據安全子系統 - 可以限制數據訪問許可權至實體屬性和表數據的行級別。並且這些所有的功能都帶有API,但是跟大家都知道的Spring Data或者JPA/Hibernate的略有不同。
所以,為什麼在CUBA中沒有上面說的查詢介面?有沒有可能添加呢?
CUBA中使用數據的方式
CUBA的API中有三個主要的類用來處理數據:DataStore,EntityManager 和 DataManager。
DataStore 的抽象是提供處理持久化存儲的API,比如RDBMS,文件系統或者雲存儲。可以通過DataStore執行基本的數據操作,但是,不推薦直接使用DataStore,除非需要開發自定義的持久化存儲或者需要對底層存儲進行非常特殊的訪問。
EntityManager 很大程度上只是JPA EntityManager 的拷貝,但是有額外的方法用來處理 CUBA視圖、軟刪除以及 CUBA 查詢語句。作為CUBA開發人員,很少在日常工作中使用這個類,除非需要剋服CUBA的安全限制。
下一個要說的,DataManager,是在CUBA中處理數據主要使用的類。此類提供了處理數據的API並且支持到屬性和行級別的 CUBA安全模型 。當查詢數據的時候,DataManager會隱式的修改查詢語句。比如,在關係型資料庫中,它會更改“select”語句,排除那些受限的屬性,然後自動添加“where”語句來篩選那些當前用戶不能看到的數據行。這種安全感知的行為是很有幫助的,開發人員不需要死記在查詢語句中需要添加哪些關於安全方面的條件。
這裡有個CUBA類交互的圖,展示使用DataManager從RDBMS中獲取數據的過程。
使用DataManager可以相對容易的查詢實體(或者使用CUBA視圖查詢實體層級結構)。最簡單的查詢是這樣:
DataManager會自己過濾掉“軟刪除”的記錄、受限制訪問的實體屬性或實體,也會自己創建資料庫事務。
但是如果需要執行帶有複雜“where”條件的查詢語句,就需要寫JPQL了。
看看最開頭那個例子,如果需要按姓統計客戶人數,在CUBA中需要寫這樣的:
這裡可以看到,需要將JPQL語句丟給DataManager去執行。在CUBA API里,JPQL需要用字元串來定義(目前還不支持Criteria API)。JPQL有很好的可讀性,也能清晰的定義一個查詢語句,但是如果出問題,可能不是很好調試。另外,JPQL字元串不像Criteria API那樣能在構建編譯時進行驗證,或者在Spring上下文初始化的時候驗證。
比較一下Spring Data JPA 的介面:
這個介面只有三分之一的代碼量而且不包含任何顯式的字元串。此外,countByLastName 方法會在部署階段驗證。如果方法名敲錯了,比如,敲成 countByLastNome,則會有異常拋出:
由於CUBA也是基於Spirng框架構建的,所以可以將Spring-data-jpa添加為CUBA項目的依賴庫然後使用這個功能。唯一的問題,Spring的查詢介面底層使用JPA的EntityManager,所以查詢語句不會被CUBA的EntityManager或者DataManager處理。因此,需要找到合適的方法在CUBA中添加查詢介面 - 需要自定義,所有調用EntityManager的地方都需要用CUBA的DataManager相應的方法替換,並且添加對CUBA視圖的支持。
也有人會說,使用Spring的方案不如CUBA的方案可控,因為不能控制生成查詢語句的過程。這是在便利性和抽象化級別之間的平衡問題,需要開發者決定到底使用那個方案。但是有個額外的處理數據的簡單方法總是沒壞處,儘管這也不是唯一的方法。
如果需要更多的控制,Spring里也有方法為介面指定查詢語句,所以這個方法也需要添加到CUBA。
實施
查詢介面使用 spring-data-commons 實現,構建為CUBA應用程式組件。這個庫包含實現自定義查詢介面的類,比如,Spring的spring-data-mongodb 庫就是基於這個實現的。Spring-data-commons利用代理技術來為聲明式查詢介面創建正確的實現。
在CUBA的上下文初始化期間,查詢介面的引用都會被生成的代理bean隱式替換。當開發人員調用介面方法時,相應的代理會進行攔截。然後代理根據方法名稱生成JPQL查詢,替換參數值,並交給DataManager執行。下圖展示了模塊關鍵組件之間的簡單交互過程。
在CUBA中使用查詢介面
需要在項目的構建文件中添加新的應用程式組件才能使用CUBA的查詢介面:
XML配置文件也需要修改啟用查詢介面:
如果習慣使用註解而不是創建XML配置文件,可以用下麵的方法啟用查詢介面:
啟用查詢介面後,可以在應用程式中創建並使用。下麵是示例:
可以在介面方法上使用 @CubaView 和 @JpqlQuery 註解。第一個註解定義需要使用的視圖(如果沒有使用這個註解預設使用“_local”視圖)。第二個註解是用來設置JPQL的,用在查詢語句不能通過方法名錶示的時候。
查詢介面的應用程式組件是綁定到CUBA的“global”模塊,所以可以在“core”和“web”模塊定義和使用查詢介面,只是別忘了在相應的配置文件中啟用介面。介面使用的示例:
結論
CUBA很靈活。如果覺得需要為應用程式添加新的功能,又不想等CUBA的新版本,很容易在不修改CUBA核心的情況下實施並添加到項目中。通過為CUBA添加查詢介面,我們希望能幫助開發人員更加有效的工作,更快的交付可靠的代碼。這個庫的第一個版本可以在GitHub找到,目前支持CUBA 6.10和更高版本。