Web服務器(Websphere、Tomcat)使用olap4j連接多維數據庫(Ssas)


最近項目需要使用Java連接到Sql Server多維數據庫(Ssas)。在網上找到了一種通過可以通過IIS發布dll來作為jdbc連接串的方法,通過開源的olap4j的jar包,成功實現了類jdbc的方式連接到ssas。但實際應用中往往是通過web服務器的jdbc連接池的方式獲得連接。 
        費了九牛二虎之力,終於成功在Tomcat和Websphere下實現了連接池。而當連接池成功創建以后,忽然發現,其實olap4j的數據庫連接池和普通的數據庫連接池根本沒有什么兩樣,只是一方面受到olap4j官網的幾句獲得連接代碼的影響(使我的方向定位在如何獲得olapConnection上,而實際上如果定位在如何獲得statement上將更會容易許多),另一方面由於olap4j有些方法沒有被實現,使得有些時候報了錯誤以為就出錯了。
一、Websphere下連接Ssas 在Tomcat下使用apache的dbcp的相關jar包的方式,通過dbcp獲得OlapCollection
第一種: 
1)JNDI配置

<Context crossContext="true" docBase="D:\lntdc\WebRoot" path="/lntdc" debug="5" reloadable="true">
 <Resource name="jdbc/ssasdb" type="javax.sql.DataSource" factory="org.apache.commons.dbcp.BasicDataSourceFactory" driverClassName="org.olap4j.driver.xmla.XmlaOlap4jDriver" maxActive="25" maxIdle="2" maxWait="5000" username="administrator" password="dcserver" url="jdbc:xmla:Server=http://10.20.14.110/olap/msmdpump.dll;Catalog=olaptest;"/>
</Context>

2)調用方式

BasicDataSource ds=(BasicDataSource)initCtx.lookup("java:comp/env/jdbc/ssasdb"); 
ds.setAccessToUnderlyingConnectionAllowed(true); 
Connection conn = ds.getConnection(); 
ds.setAccessToUnderlyingConnectionAllowed(true);//從ds對象的私有方法中獲得對象 
DelegatingConnection connection = (DelegatingConnection) conn; 
OlapWrapper wrapper = (OlapWrapper) connection.getInnermostDelegate(); 
OlapConnection olapConnection = wrapper.unwrap(OlapConnection.class); 
OlapStatement stmt = (OlapStatement)olapConnection.createStatement(); 
CellSet cellSet = stmt.executeOlapQuery(sql);//sql為mdx語句 

上面這段代碼還可以用下面這段取代:

BasicDataSource ds=(BasicDataSource)initCtx.lookup("java:comp/env/jdbc/ssasdb"); 
GenericObjectPool pool = new GenericObjectPool(null); 
ConnectionFactory factory = new DataSourceConnectionFactory(ds); 
PoolableConnectionFactory poolableFactory = new PoolableConnectionFactory(factory, pool, null, null, false, true); 
PoolingDataSource poolingDataSource = new PoolingDataSource(pool); 
ds.setAccessToUnderlyingConnectionAllowed(true); 
poolingDataSource.setAccessToUnderlyingConnectionAllowed(true);//與前面一句缺一不可。 
Connection conn = ds.getConnection(); 
System.out.println("Sql Base Connection get Sucessful!"); 
DelegatingConnection connection = (DelegatingConnection) poolingDataSource.getConnection(); 
OlapWrapper wrapper = (OlapWrapper) connection.getInnermostDelegate();

第二種: 1)JNDI配置

<Resource name="jdbc/ssasdb" type="org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS" factory="org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS" driver="org.olap4j.driver.xmla.XmlaOlap4jDriver" maxActive="25" maxIdle="2" maxWait="5000" user="administrator" password="dcserver" url="jdbc:xmla:Server=http://10.20.14.110/olap/msmdpump.dll;Catalog=olaptest;"/>

注意:上面的配置中與一般的tomcat數據源配置不同,user和driver屬性,這兩個要必需是DriverAdapterCPDS類的屬性。

 
<span style="line-height: 1.714285714; font-size: 15px; font-family: 仿宋;">2)調用方式</span> 
DriverAdapterCPDS ds=(DriverAdapterCPDS)initCtx.lookup("java:comp/env/jdbc/ssasdb"); 
Connection conn=ds.getPooledConnection().getConnection(); 
OlapStatement stmt = (OlapStatement)conn.createStatement(); 
CellSet cellSet = stmt.executeOlapQuery(sql);

二、Websphere下連接Ssas
1)jdbc提供程序配置
類路徑

olap4j-1.0.0.445.jar
olap4j-tck-1.0.0.445.jar
olap4j-xmla-1.0.0.445.jar
commons-dbcp-1.2.1.jar
commons-pool-1.2.jar
commons-collections.jar

實現類名 org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS
jdbc-provider 
2)jdbc數據源配置 數據庫存儲器help類名 com.ibm.websphere.rsadapter.GenericDataStoreHelper jdbc-datasource 定制屬性:一般是DriverAdapderCPDS類的屬性
url:jdbc:xmla:Server=http://10.20.14.110/olap/msmdpump.dll;Catalog=olaptest driver:org.olap4j.driver.xmla.XmlaOlap4jDriver
ds-field
        到此為止,再加上配個jcc 認證(連接olap數據源的用戶和密碼),就可以測試連接了。 在連接成功時,Websphere會報GenericDataStoreHelper 正在使用的警告,但沒發現這種警告對數據庫連接有什么影響。 
3)調用方式

 
DataSource ds=(javax.sql.DataSource)initCtx.lookup("jdbc/ssasdb"); 
Connection sc=ds.getConnection(); 
Class clazz=sc.getClass(); 
Method method=clazz.getDeclaredMethod("getJDBCImplObject"); 
method.setAccessible(true); 
Connection oo=(java.sql.Connection)method.invoke(sc); 
OlapStatement stmt = (OlapStatement)oo.createStatement(); 
CellSet cellSet = stmt.executeOlapQuery(sql);//這里使用java的反射機制獲得OlapStatement對象。

        在做到這一步之前,我曾經嘗試過如何在Websphere中獲得OlapCollection的對象,但最終沒有成功,其實上面的getJDBCImplObject方法也只能獲得ConnectionImpl類的對象,而該類只是個私有類,因此無法獲得到該類的實例。
        WebSphere在建立連接池時把ConnectionImpl對象封裝在com.ibm.ws.rsadapter.jdbc.WSJdbcConnection類的受保護的屬性connImpl中,而該屬性是在WSJdbcConnection的構造方法中賦值的,而這個構造方法在class com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource類中被調用,並生成WSJdbcConnection對象。
        我曾經嘗試通過如下方式獲得OlapCollection的對象,當我獲得到dbcp的poolingDataSource時,我以為能夠獲得到Olapcollection,但最終獲得的仍然是WSJdbcConnection的對象(其實想想也該如此):

 
Context context = new javax.naming.InitialContext(); 
DataSource ds = (javax.sql.DataSource)context.lookup("jdbc/ssasdb"); 
GenericObjectPool pool = new GenericObjectPool(null); 
ConnectionFactory factory = new DataSourceConnectionFactory(ds); 
PoolableConnectionFactory poolableFactory = new PoolableConnectionFactory(factory, pool, null, null, false, true); 
PoolingDataSource poolingDataSource = new PoolingDataSource(pool); 
poolingDataSource.setAccessToUnderlyingConnectionAllowed(true); 
DelegatingConnection connection = (DelegatingConnection) poolingDataSource.getConnection();

        Websphere把OlapConnection封裝在WSJdbcConnection中(其實tomcat也把它封裝在相應的自己實現類中,但可以通過設置factory屬性修改這個封裝類而已),這種封裝將使得獲得到這樣的類的實例很困難(除非使用java的反射機制),但實際上,在這種機制下,一般的數據庫的jdbc的connection並不需要顯式地獲得到這樣的實例,其實WSJdbcConnection的相關數據庫執行(增刪改查等)方法都是調用被封裝的實例的方法,而WSJdbcConnection只是為所有各種類型的數據庫查詢所提供的統一接口而已,並且WSJdbcConnection這個類也不需要顯式地獲得,只需要把它強轉成Connection的實例即可。
        只是Olap多維數據庫的Olap4j驅動程序一般(指官方幫助)使用OlapStatement.excuteOlapQuery方法獲得數據,並且獲得的數據類型是CellSet,因此我最初認為只有通過這種方式獲得OlapConnection,然后OlapStatement,才能獲得到結果,因此花費了很大力氣去獲得OlapConnection,而這種對象被web服務器封裝起來了,而且不同服務器的封裝變量不同,獲得到這樣的對象並不容易。
        其實根本沒必要獲得這樣的對象,因為Olap4j與普通的數據庫驅動程序其實是一回事,只是我使用了excuteOlapQuery方法而忽略了excuteQuery方法,而如果使用OlapConnection的excuteQuery方法,Olap4j與普通數據庫驅動一樣,我們不需要顯式地獲得OlapConnection對象,只需要使用WSJdbcConnection作為java.sql.Connection,然后getStatement,excuteQuery就可以了,只是需要把XmlaOlapStatement里的默認情況下未被實現的方法excuteQuery實現一下即可,只需在這個方法中使用excuteOlapQuery方法獲得CellSet,然后把它轉換成ResultSet即可。
        其實還是對jdbc的機制(可能也包括Olap4j)不是很了解,導致繞了一個大大的圈子。
注:本文檔基於olap4j1.0.445版本編寫。

附件
修改后OlapSource.zip ,提取密碼:hqlm
olap4j-xmla-1.0.0.445.jar ,提取密碼:qnoe
olap4j-1.0.0.445.jar ,提取密碼:e388
olap4j-tck-1.0.0.445.jar ,提取密碼:6txq


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM