Java 如何呼叫 SPL 指令碼
集算器提供了 JDBC 驅動,很容易嵌入到 Java 程式呼叫,方法和在 Java 中執行 SQL 和儲存過程類似。
去乾學院看個究竟:Java 如何呼叫 SPL 指令碼
複製摘要
Java 應用程式中部署集算器 JDBC
首先將 JDBC 部署到 java 應用專案中,簡單來說就是,將啟動 JAVA 應用程式時載入集算器所需的 jar 包及配置檔案放到專案中。需要注意的是,集算器 JDBC 所要求的 JDK 版本不得低於 1.6。
1. 載入驅動 jar
集算器 JDBC 類似一個不帶物理表的資料庫 JDBC 驅動,可以把它簡單的看成是一個只有儲存過程的資料庫。另外,集算器 JDBC 是個完全嵌入式計算引擎,已經在 JDBC 中完成了所有運算,不象資料庫那樣 JDBC 只是個介面,實際運算在獨立的資料庫伺服器完成。
如果在 web 應用專案下,可以把這些 jar 包放在 WEB-INF/lib 目錄下。集算器 JDBC 需要三個基礎 jar 包,都可以在 [安裝目錄]\esProc\lib 目錄下找到:
dm.jar icu4j_3_4_5.jar jdom.jar
dm.jar //集算器計算引擎及JDBC驅動包 icu4j_3_4_5.jar //處理國際化 jdom.jar //解析配置檔案
除了以上的必需 jar,還有一些為完成特定功能的 jar 包:
比如資料庫作為資料來源,那麼還需要相應資料庫的驅動 jar 包;
要讀寫 Office 檔案,則需要加入 poi*.jar 和 xmlbeans.jar;
要使用繪製圖形功能,則需要加入 SVG 圖形處理相關的 jar 包,包括 batik*.jar、js.jar、pdf-transcoder.jar、xalan-2.6.0.jar、xercesImpl.jar、xml-apis.jar、xml-apis-ext.jar。
2. 部署 raqsoftConfig.xml
集算器還有個重要的配置檔案 raqsoftConfig.xml,可以在 [安裝目錄]\esProc\config 下找到,需複製後放置在應用專案的類路徑下,配置檔案的名稱不可改變。
在 raqsoftConfig.xml 檔案中,配置了授權資訊、集算器主路徑、dfx 檔案定址路徑等各類資訊。我們先看下最基本的配置,即集算器授權檔案配置:
<?xml version="1.0" encoding=" UTF-8"?> < Config Version="2"> <Runtime> <Esproc> <license>esproc.xml</license> </Esproc> </Runtime> </Config>
<?xml version="1.0" encoding=" UTF-8"?> < Config Version="2"> <Runtime> <Esproc> <!--集算器授權檔案配置,可以是絕對路徑,也可以是相對路徑,使用相對路徑時是相對於類路徑--> <license>esproc.xml</license> <!--試用授權檔案可從潤乾公司官網中下載--> </Esproc> </Runtime> </Config>
Java 呼叫
Java 程式中呼叫 SPL 指令碼 ,與 java 中呼叫 SQL 和儲存過程類似,下面來看下具體是怎樣實現的:
執行 SPL 語句
比如建立一個數據表,並新增兩個欄位 baseNum、square2,分別將 100 以內的自然數及其的平方值組成 100 條記錄插入到資料表中,最後將表中的資料作為結果集返回。
Java 程式碼如下:
public void runSPL() throws ClassNotFoundException, SQLException{ Connection con = null; PreparedStatement st; ResultSet set ; Class._forName_("com.esproc.jdbc.InternalDriver"); con= DriverManager._getConnection_("jdbc:esproc:local://"); st = (PreparedStatement)con.createStatement(); ResultSet rs = st.executeQuery("=100.new(~:baseNum,~*~:square2)"); ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount(); for ( int c = 1; c <= colCount;c++) { String title = rsmd.getColumnName(c); if( c > 1 ) { System._out_.print("\t"); } else { System._out_.print("\n"); } System._out_.print(title); } while (rs.next()) { for(int c = 1; c<= colCount; c++) { if ( c > 1 ) { System._out_.print("\t"); } else { System._out_.print("\n"); } Object o = rs.getObject(c); System._out_.print(o_.toString()); } } if (con!=null) { con.close(); }
public void runSPL() throws ClassNotFoundException, SQLException{ Connection con = null; PreparedStatement st; ResultSet set ; //建立連線 Class._forName_("com.esproc.jdbc.InternalDriver"); con= DriverManager._getConnection_("jdbc:esproc:local://"); //直接執行SPL語句,返回結果集 st = (PreparedStatement)con.createStatement(); ResultSet rs = st.executeQuery("=100.new(~:baseNum,~*~:square2)"); //簡單處理結果集,將結果集中的欄位名與資料輸出 ResultSetMetaData rsmd = rs.getMetaData(); int colCount = rsmd.getColumnCount(); for ( int c = 1; c <= colCount;c++) { String title = rsmd.getColumnName(c); if( c > 1 ) { System._out_.print("\t"); } else { System._out_.print("\n"); } System._out_.print(title); } while (rs.next()) { for(int c = 1; c<= colCount; c++) { if ( c > 1 ) { System._out_.print("\t"); } else { System._out_.print("\n"); } Object o = rs.getObject(c); System._out_.print(o_.toString()); } } //關閉連線 if (con!=null) { con.close(); }
執行結果:
在 SPL 中訪問本地檔案
通過 SPL 還可以訪問本地的檔案,其中包括 Txt、Excel、Json、Csv、Ctx 等多種型別的檔案,訪問時可以通過絕對路徑查檔案位置,也可以通過相對路徑查詢,使用相對路徑時,則是相對於配置檔案中的主目錄,所以,首先我們來配置下主目錄:
在 raqsoftConfig.xml 檔案的節點 < Esproc ></ Esproc > 中新增以下節點:
<mainPath>D:\mainFile</mainPath>
<!--集算器主路徑,該路徑為單一的絕對路徑--> <mainPath>D:\mainFile</mainPath>
我們把要呼叫的檔案 employee.txt 放到主目錄下面,在 JAVA 中呼叫時,建立連線、輸出結果等部分的程式碼與上例是完全相同的,呼叫 SPL 語句部分如下:
ResultSet rs=st.executeQuery("=file(\"D:\mainFile\employee.txt\")[email protected]()");
ResultSet rs=st.executeQuery("=file(\"D:\mainFile\employee.txt\")[email protected]()");
這裡支援絕對路徑與相對路徑的使用,在 Java 中使用反斜槓 \ 表示轉義符。
執行結果:
對於這種簡單運算,還可以使用簡單 SQL 語法:
ResultSet rs=st.executeQuery("$()select * from employee.txt");
ResultSet rs=st.executeQuery("$()select * from employee.txt");
其中 $() 表示訪問本地檔案系統,兩種寫法的結果集相同。
帶引數的 SPL 語句
引數是 SQL 語句的一個重要組成部分,同樣,SPL 語句中也支援引數的使用,例如,像上例中,要查詢 employee.txt 檔案中的資料,但是要求只查詢工資在 12000 到 20000 之間的記錄,並根據工資升序排序:
呼叫部分程式碼如下:
PreparedStatement pst = con.prepareStatement("$()select * from employee.txt where SALARY > ? and SALARY< ? order by SALARY"); pst.setObject(1,12000); pst.setObject(2,20000); ResultSet rs = pst.executeQuery();
PreparedStatement pst = con.prepareStatement("$()select * from employee.txt where SALARY > ? and SALARY< ? order by SALARY"); //設定引數 pst.setObject(1,12000); pst.setObject(2,20000); ResultSet rs = pst.executeQuery();
其中用?表示引數,然後通過 setObject() 為上面的引數一一賦值。
執行結果:
有資料來源的 SPL 語句
集算器 JDBC 既然是個資料計算引擎,那麼資料來源的重要途徑之一就是資料庫了,JAVA 中如何來呼叫帶資料來源的 SPL 語句呢?往下看:
JAVA 呼叫帶資料來源的 SPL 語句之前,需要先在應用專案中新增對應的資料庫驅動,然後在配置檔案 raqsoftConfig.xml 中配置資料來源資訊。
例如:呼叫的 SPL 語句中使用的資料來源名稱為 demo,資料庫型別為 HSQL,那麼配置如下:
首先,將 HSQL 的資料集驅動 hsqldb.jar 載入到應用專案中;
其次,在 raqsoftConfig.Xml 的 < Runtime ></ Runtime > 節點中配置資料來源資訊:
<DBList> <DB name="demo"> <property name="url" value="jdbc:hsqldb:hsql://127.0.0.1/demo" ></property> <!-- urlè¿æ¥--> <property name="driver" value="org.hsqldb.jdbcDriver" ></property> <!--æ°æ®åºé©±å¨--> <property name="type" value="13" ></property> <!--æ°æ®åºç±»å--> <property name="user" value="sa" ></property> <!--ç¨æ·å--> <property name="password" value=""></property> <!--å¯ç --> <property name="batchSize" value="1000" ></property> <property name="autoConnect" value="true" ></property><! <property name="useSchema" value="false" ></property> <property name="addTilde" value="false" ></property> <property name="dbCharset" value="UTF-8" ></property> <property name="clientCharset" value="UTF-8" ></property> <property name="needTransContent" value="false" ></property> <property name="needTransSentence" value="false" ></property> <property name="caseSentence" value="false" ></property> </DB> </DBList>
<DBList> <DB name="demo"> <!--資料來源名稱--> <property name="url" value="jdbc:hsqldb:hsql://127.0.0.1/demo" /> <!-- url連線--> <property name="driver" value="org.hsqldb.jdbcDriver" /> <!--資料庫驅動--> <property name="type" value="13" /> <!--資料庫型別--> <property name="user" value="sa" /> <!--使用者名稱--> <property name="password" value=""/> <!--密碼--> <property name="batchSize" value="1000" /> <property name="autoConnect" value="true" /><!--是否自動連線,如果設定為true,則可以直接以$開頭的SQL語句來訪問資料庫,如果為false,則不會自動連線,使用前必須用connect(db)語句建立資料庫連線--> <property name="useSchema" value="false" /> <property name="addTilde" value="false" /> <property name="dbCharset" value="UTF-8" /> <property name="clientCharset" value="UTF-8" /> <property name="needTransContent" value="false" /> <property name="needTransSentence" value="false" /> <property name="caseSentence" value="false" /> </DB> </DBList>
現在我們通過 SPL 從 demo 資料來源中查詢 SALES 表,過濾出 SELLERID 為 3 的員工,在 2014 年 11 月 11 號到 2014 年 12 月 12 號期間的所有訂單資訊:
呼叫部分程式碼如下:
PreparedStatement pst = con.prepareStatement("$(demo)select * from SALES where SELLERID = ? and ORDERDATE>? and ORDERDATE<?"); pst.setObject(1,"3"); pst.setObject(2,java.sql.Date.valueOf("2014-11-11")); pst.setObject(3,java.sql.Date.valueOf("2014-12-12")); ResultSet rs = pst.executeQuery();
PreparedStatement pst = con.prepareStatement("$(demo)select * from SALES where SELLERID = ? and ORDERDATE>? and ORDERDATE<?"); //設定引數 pst.setObject(1,"3"); pst.setObject(2,java.sql.Date.valueOf("2014-11-11")); pst.setObject(3,java.sql.Date.valueOf("2014-12-12")); //獲取結果集 ResultSet rs = pst.executeQuery();
結果集輸出如下:
執行 SPL 指令碼
JAVA 整合集算器 JDBC 後,除了可以直接執行單句的 SPL 語句,還可以呼叫更復雜的 SPL 指令碼(字尾為 dfx 的檔案)。
比如下面的 dfx 檔案:
A | B | C | |
1 | =demo.query("select NAME as CITY, STATEID as STATE from CITIES") |
[] |
|
2 | for A1 |
=demo.query("select * from STATES where STATEID=?",A2.STATE) |
|
3 | if left(B2.ABBR,1)==arg1 |
>A2.STATE=B2.NAME |
|
4 | >B1=B1|A2 |
||
5 | return B1 |
SPL 指令碼思路:
迴圈遍歷 CITIES 表記錄,通過 CITIES. STATES 過濾 STATES 表,若 STATES. ABBR 首字母為引數 arg1,則將 STATES 表中的 NAME 值賦給 CITIES. STATE,並將 CITIES 表中的這條記錄拼接到 B1 格中,最終返回 B1 格的結果集。
在這個網格檔案中,需要從資料來源 demo 中獲取資料,同時使用了引數 arg1:
資料來源配置方法可以參考上面的示例,網格檔案儲存為 city.dfx,dfx 檔案可以存放在應用專案類路徑或 raqsoftConfig.xml 中配置的主目錄下,當 dfx 檔案比較多的時候,為了便於統一維護和管理,我們還可以將 dfx 檔案放到 dfx 定址路徑中,定址路徑的配置方式如下:
在 raqsoftConfig.xml 檔案的 < Esproc></ Esproc> 節點中,新增以下內容:
<dfxPathList> <dfxPath>D:\dfxFile</dfxPath> </dfxPathList>
<dfxPathList> <!--配置dfx檔案定址路徑,該路徑為絕對路徑,可以設定多個路徑,以“;”隔開--> <dfxPath>D:\dfxFile</dfxPath> </dfxPathList>
呼叫部分程式碼如下:
st =con.prepareCall("call city(?)"); st.setObject(1, "A"); ResultSet rs = st.executeQuery();
//通過call呼叫儲存過程,其中city是dfx的檔名,?表示引數,多個引數間用逗號間隔 st =con.prepareCall("call city(?)"); st.setObject(1, "A"); //獲取結果集 ResultSet rs = st.executeQuery();
通過 call 呼叫 dfx 檔案除了上面的寫法,還可以在呼叫 dfx 時直接傳參,如下:
st=con.prepareStatement("call city(\"A\")"); ResultSet rs = st.executeQuery();
st=con.prepareStatement("call city(\"A\")"); //獲取結果集 ResultSet rs = st.executeQuery();
執行結果:
在 Java 中呼叫 dfx 檔案時,也可以省略 call 直接使用 dfx (…),該用法同樣有兩種寫法,如下:
st =con.prepareCall("city ?"); st.setObject(1,"A");
//dfx名稱與引數間以空格作為分隔,多個引數間通過逗號分隔 st =con.prepareCall("city ?"); //設定引數 st.setObject(1,"A");
或:
st =con.prepareCall("city \"A\"");
st =con.prepareCall("city \"A\"");
以上幾種呼叫方法最終獲取的結果集均相同。
上述內容就是 Java 呼叫 SPL 指令碼的常用方式了,想了解更多用法的小夥伴兒可以去官網上的線上教程中檢視
作者:ddszm
連結:http://c.raqsoft.com.cn/article/1543657951867
來源:乾學院
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。