天天看點

Java如何調用SPL腳本

【摘要】

集算器提供了 JDBC 驅動,很容易嵌入到 Java 程式調用,方法和在 Java 中執行 SQL 和存儲過程類似。

結構圖如下:

Java如何調用SPL腳本
首先将 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  //集算器計算引擎及JDBC驅動包
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://");
    //直接執行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();
   } 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();
   }      

執行結果:

Java如何調用SPL腳本

在 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\").import@t()");ResultSet rs=st.executeQuery("=file(\"D:\mainFile\employee.txt\").import@t()");      

這裡支援絕對路徑與相對路徑的使用,在 Java 中使用反斜杠 \ 表示轉義符。

Java如何調用SPL腳本

對于這種簡單運算,還可以使用簡單 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() 為上面的參數一一指派。

Java如何調用SPL腳本

有資料源的 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><!--是否自動連接配接,如果設定為true,則可以直接以$開頭的SQL語句來通路資料庫,如果為false,則不會自動連接配接,使用前必須用connect(db)語句建立資料庫連接配接-->
<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();      

結果集輸出如下:

Java如何調用SPL腳本

執行 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:

Java如何調用SPL腳本

資料源配置方法可以參考上面的示例,網格檔案儲存為 city.dfx,dfx 檔案可以存放在應用項目類路徑或 raqsoftConfig.xml 中配置的主目錄下,當 dfx 檔案比較多的時候,為了便于統一維護和管理,我們還可以将 dfx 檔案放到 dfx 尋址路徑中,尋址路徑的配置方式如下:

在 raqsoftConfig.xml 檔案的 < Esproc></ Esproc> 節點中,添加以下内容:

<dfxPathList>
   <!--配置dfx檔案尋址路徑,該路徑為絕對路徑,可以設定多個路徑,以“;”隔開-->  
   <dfxPath>D:\dfxFile</dfxPath>
</dfxPathList><dfxPathList>
   <!--配置dfx檔案尋址路徑,該路徑為絕對路徑,可以設定多個路徑,以“;”隔開-->  
   <dfxPath>D:\dfxFile</dfxPath></dfxPathList>      
//通過call調用存儲過程,其中city是dfx的檔案名,?表示參數,多個參數間用逗号間隔
  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如何調用SPL腳本

在 Java 中調用 dfx 檔案時,也可以省略 call 直接使用 dfx (…),該用法同樣有兩種寫法,如下:

//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 腳本的常用方式了,其他程式調用 SPL 的用法: