Web服务器(Websphere、Tomcat)使用olap4j连接多维数据库(Ssas)
Posted on 2017-07-21 15:47 空余恨 阅读(2322) 评论(0) 编辑 收藏 举报最近项目需要使用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
2)jdbc数据源配置 数据库存储器help类名 com.ibm.websphere.rsadapter.GenericDataStoreHelper
定制属性:一般是DriverAdapderCPDS类的属性url:jdbc:xmla:Server=http://10.20.14.110/olap/msmdpump.dll;Catalog=olaptest driver:org.olap4j.driver.xmla.XmlaOlap4jDriver
到此为止,再加上配个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