Java如何調用SPL腳本

【摘要】

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

結構圖如下:
imagepng


首先將 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();
   }

執行結果:

imagepng

在 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 中使用反斜槓 \ 表示轉義符。

執行結果:

imagepng

對於這種簡單運算,還可以使用簡單 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() 爲上面的參數一一賦值。

執行結果:

imagepng

有數據源的 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();

結果集輸出如下:

imagepng

執行 SPL 腳本

JAVA 集成集算器 JDBC 後,除了可以直接執行單句的 SPL 語句,還可以調用更復雜的 SPL 腳本(後綴爲 dfx 的文件)。
比如下面的 dfx 文件:



ABC
1=demo.query("select NAME as CITY, STATEID as STATE from   CITIES")[]
2for 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
5return B1


SPL 腳本思路:
循環遍歷 CITIES 表記錄,通過 CITIES. STATES 過濾 STATES 表,若 STATES. ABBR 首字母爲參數 arg1,則將 STATES 表中的 NAME 值賦給 CITIES. STATE,並將 CITIES 表中的這條記錄拼接到 B1 格中,最終返回 B1 格的結果集。
在這個網格文件中,需要從數據源 demo 中獲取數據,同時使用了參數 arg1:

imagepng

數據源配置方法可以參考上面的示例,網格文件保存爲 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();

執行結果:

imagepng

在 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 的用法:

Birt 調用 SPL 腳本
JasperReport 調用 SPL 腳本
C# 如何調用 SPL 腳本
Java 如何遠程調用 SPL 腳本
HTTP 調用 SPL

想了解更多用法的小夥伴兒可以去官網上的在線教程中查看


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章