olap分析平台的设计与实现(十七)- springboot集成mondrian

开发环境搭建:

1个想法一通向导搞定spring boot

ps:使用IDEA构建一个SpringBoot + Hibernate + Gradle项目

这一步,算是建造了spring + hibernate,后面还有连接池,换成mybatis的问题。

idea中Alt + Enter导入包,和eclipse有点不一样。

甲骨文罐子??:ps:  gradle开发springboot项目,连接甲骨文数据库

然后狂建一堆model .....

测试运行一遍:报错:

java.lang.IllegalArgumentException: Not a managed type: class com.comm.f_olap.model.CommObject...

。实体类加上注解啥的,问题解决。

@Entity
@Table(name = "user")//数据库的表名
public class CommObject {
	@Id
	private int id;
	@Column(name = "name")//数据库的字段名,数据库 不区分大小写 这个 要注意
.....

连接池:

ps:深入理解Spring Boot数据源与连接池原理

spring boot自带了连接池?测试一把:

@SpringBootTest
class FOlapApplicationTests {
    @Autowired
    DataSource dataSource;

    @Test
    void contextLoads() {
        System.out.println(dataSource.getClass());
    }

}

结果:com.zaxxer.hikari.HikariDataSource类。

貌似HikariDataSource蛮强大,本想约会德鲁伊,有了可用的连接池,就不看其他的,否则,我可能还得做加配置文件等工作。

HikariDataSource是spring boot2才约会的。

ps:本想约会德鲁伊:

build.gradle:中加一行:

compile group: 'com.alibaba', name: 'druid', version: '1.1.10'

属性文件(application.properties)如下:

server:
    port: 8881
    max-http-header-size: 102400

spring:
    datasource:
        url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
        username: SUPERVISION
        password: 1
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: oracle.jdbc.OracleDriver
        druid:
            initial-size: 1
            min-idle: 1
            max-active: 300
            max-wait: 60000
            time-between-eviction-runs-millis: 60000
            min-evictable-idle-time-millis: 30000
            validation-query: SELECT 'x' from dual
            test-while-idle: true
            test-on-borrow: false
            test-on-return: false
            pool-prepared-statements: true
            max-pool-prepared-statement-per-connection-size: 20
            filters: stat,slf4j
            connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
            web-stat-filter.enabled: true
            web-stat-filter.principal-session-name: username
            stat-view-servlet.enabled:  true
            stat-view-servlet.url-pattern:  /druid/*
    jpa:
        show-sql: true
        database: oracle
        properties:
            hibernate:
                dialect: org.hibernate.dialect.OracleDialect
                enable_lazy_load_no_trans: true
        open-in-view: true

运行报错:应该是还要加一个配置文件,既然用HikariDataSource,这个就不进行下去了。

ps:相关参考:用到时候,参考一下,这里先记下。

  1. 深入了解Spring Boot数据源与连接池原理
  2.  
  3. Spring Boot集成Druid连接池(MySQL8.0.11)
  4. springBoot + gradle + Oracle配置德鲁伊
  5. springboot多数据源(三种数据库连接池--JDBC,dbcp2,Druid)
  6.  
  7. Springboot整合Druid,添加拦截器进行数据监控
  8. springboot添加德鲁伊步骤
  9. Springboot + Mybatis的+ dbcp + MySQL的简单集成
  10. springboot配置数据库连接池
  11. SpringBoot配置连接池
  12. springboot添加druid步骤(两种方案)
  13. springboot2.0整合德鲁伊,以及springboot自动装配DataSource原理

持久层考虑因素:

        1,我们要集成mondrian,mondrian好像是jdbc直连,所以测试一下mondrian集成在spring boot 2.0下的表现。

                       从2个方面测试,一个是mondrian直联jdbc,一个是和spring boot jdbc template Integrated?

        2,我们项目用hibernate还是mybatis?

                     hibernate?对我来说,类是继承的pojo,hibernate如何实现,得测试一遍。

                      mybatis?貌似蛮灵活,但可以点击,也得测试一遍。

        因此,我们要从三个方面进行测试:

  1.                       mondrian集成;
  2.                       hibrenate中,pojo是继承关系的rud测试。
  3.                       mybatis测试。    

spring boot环境下 mondrian集成:

    mondrian集成?参考我前面写的《非税olap分析平台的设计与实现(二)_测试开发配置》。

ps:Zxing的集成---- Maven对应Gradle的写法

测试不成功,可能是代理,GW惹的祸?

不管它:

直接约会lib,

gradle中,加入 dependencies{compile files('lib/mondrian-4.7.0.0-12.jar')} ok!

搭建环境中,没必要掌握所有细节,还是得以解决问题为导向。

mondrian集成过程:gradle中添加如下内容(也许有多的jar):

    dependencies{compile files('lib/mondrian-4.7.0.0-12.jar')}
    dependencies{compile files('lib/eigenbase-xom-1.3.4.jar')}
    dependencies{compile files('lib/eigenbase-resgen-1.3.1.jar')}
    compile group: 'org.olap4j', name: 'olap4j', version: '1.2.0'
    compile group: 'org.olap4j', name: 'olap4j-xmlaserver', version: '1.2.0'
    //compile group: 'eigenbase', name: 'eigenbase-xom', version: '1.3.4'
    compile group: 'net.hydromatic', name: 'eigenbase-properties', version: '1.1.5'
    //compile group: 'eigenbase', name: 'eigenbase-resgen', version: '1.3.1'
    compile group: 'commons-math', name: 'commons-math', version: '1.2'
    compile group: 'apache-log4j', name: 'log4j', version: '1.2.14'
    compile group: 'commons-vfs', name: 'commons-vfs', version: '1.0'
    compile group: 'org.apache.commons', name: 'commons-vfs2', version: '2.1'

但 测试运行报错:

org.apache.commons.vfs.FileSystemException: Could not create a file system manager of class "org.apache.commons.vfs.impl.StandardFileSystemManager".
	at org.apache.commons.vfs.VFS.createManager(VFS.java:93)
	at org.apache.commons.vfs.VFS.getManager(VFS.java:47)
	at mondrian.spi.impl.ApacheVfsVirtualFileHandler.readVirtualFile(ApacheVfsVirtualFileHandler.java:37)
	at mondrian.olap.Util.readVirtualFile(Util.java:3479)
	at 
......
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal
	at java.lang.ClassLoader.defineClass1(Native Method)
	......
Caused by: java.lang.ClassNotFoundException: org.w3c.dom.ElementTraversal
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 97 more

java.lang.NoClassDefFoundError: org/apache/commons/collections/map/ReferenceMap

	......
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.collections.map.ReferenceMap
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 78 more

提示差java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal ,百度一番,发现这个jar 报名是xml-apis

ps:java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal 的解决办法

打开原来maven引用的情况如下:

可以看到,olap4j 依赖xml_apis.jar,

我这里是complie引用该jar,因此,(gradle 没有优先读本地maven?这方式没有加载olap4j 所依赖的库?或者maven库有问题?)

另外ClassNotFoundException:org.apache.commons.collections.map.ReferenceMap,这个问题,是差commons-collections。

重新引入它,运行测试,报错:

2019-11-14 13:59:36.548  INFO 83320 --- [           main] o.a.c.vfs.impl.DefaultFileReplicator     : Using "C:\Users\tbxc\AppData\Local\Temp\vfs_cache" as temporary files store.
mondrian.olap.MondrianException: Mondrian Error:Internal error: Virtual file is not readable: FSCK_MDX.xml
	at mondrian.resource.MondrianResource$_Def0.ex(MondrianResource.java:989)
	at mondrian.olap.Util.newInternal(Util.java:2536)
	at mondrian.olap.Util.newError(Util.java:2551)
	at 
......

mondrian.olap.MondrianException: Mondrian Error:Connect string must contain property 'Catalog' or property 'CatalogContent'

	at mondrian.resource.MondrianResource$_Def1.ex(MondrianResource.java:1009)
	......

文件路径不对?重新copy路径如下图:

ok! 测试通过!

完整gradle如下:

plugins {
    id 'org.springframework.boot' version '2.2.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
}

group = 'com.Comm'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    mavenCentral()
}

dependencies {

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-web-services'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'



    implementation('org.springframework.boot:spring-boot-starter-actuator')
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
    implementation('org.springframework.boot:spring-boot-starter-jdbc')
    implementation('org.springframework.boot:spring-boot-starter-web')
    testImplementation('org.springframework.boot:spring-boot-starter-test')

    dependencies{compile files('lib/ojdbc6.jar')}

    dependencies{compile files('lib/mondrian-4.7.0.0-12.jar')}
    dependencies{compile files('lib/eigenbase-xom-1.3.4.jar')}
    dependencies{compile files('lib/eigenbase-resgen-1.3.1.jar')}
    dependencies{compile files('lib/xml-apis-1.4.01.jar')}
    compile group: 'org.olap4j', name: 'olap4j', version: '1.2.0'
    compile group: 'org.olap4j', name: 'olap4j-xmlaserver', version: '1.2.0'

    compile group: 'net.hydromatic', name: 'eigenbase-properties', version: '1.1.5'

    compile group: 'commons-math', name: 'commons-math', version: '1.2'
    compile group: 'apache-log4j', name: 'log4j', version: '1.2.14'
    compile group: 'commons-vfs', name: 'commons-vfs', version: '1.0'
    compile group: 'org.apache.commons', name: 'commons-vfs2', version: '2.1'
    compile group: 'commons-collections', name: 'commons-collections', version: '3.2.2'

}

test {
    useJUnitPlatform()
}

hibernate5:

继承关系的测试:

//父类
@Entity
@Table(name = "COMMOBJECT")//数据库的表名
@Inheritance(strategy = InheritanceType.JOINED)
public class CommObject {
	@Id
	private int id;
	@Column(name = "name")//数据库的字段名,数据库 不区分大小写 这个 要注意
	private String name;
....

//子类

@Entity
@Table
@PrimaryKeyJoinColumn(name = "id")
public class FormFolder extends CommObject {
....

以前我都是写配置文件,这次换注解,测试通过。

参考文档:

spring-data-jpa实现继承实体类详解

Hibernate继承注解

SpringBoot 与JPA结合中 JpaRepository 里自定义查询

ibats?算了,用hibernate就够了!

原型需要的数据:

开发先做关键原型,接下来准备各种原型需要的数据。

先准备维度数据:年度、期间、版本、币别、场景、项目、组织

                                                                             (维度的管理类) 

一个具体维度,数据库上有三张表反映:

                                                                             (维度及mondrian相关表) 

维度相关的表:

  1. commObject,所有原始的祖先表;
  2. 前缀为 “c_” 的表,用于管理各类维度。
  3. 前缀为““c_dim_”的表,是mondrain引擎用到维度表。

配置mondrian的schemal相关的维度表用"c_dim_"前缀开头。

维度数据准备,以后应该用kettle抽取?

由于我先搞了一个项目维度表,感觉内容多了,相关数据重新迁移到commobject表。

  select p.projectkey + 500000,
         p.projectname,
         1,
         -100,    --上级id 下面再处理
         case   --代数
           when p.projectcode = p.level1projectcode then
            1
           when p.projectcode = p.level2projectcode then
            2
           when p.projectcode = p.level3projectcode then
            3
           when p.projectcode = p.level4projectcode then
            4
           when p.projectcode = p.level5projectcode then
            5
           when p.projectcode = p.level6projectcode then
            6
           when p.projectcode = p.level7projectcode then
            7
           when p.projectcode = p.level8projectcode then
            8
         end,
         
         case p.isleaf   --是否有子节点
           when '0' then
            1
           when '1' then
            0
         end,
         rank,
         0,
         to_timestamp(to_char(sysdate, 'yyyy-mm-dd hh24:mi:ss'),     --时间戳
                      'yyyy-mm-dd hh24:mi:ss')
    from dim_chargeproject p,
         
         (select p.projectkey projectkey,
                 p.projectcode,
                 p.projectname
                 
                ,
                 rank() over(order by p.projectcode) rank   --排序号 可能有问题
            from dim_chargeproject p) pr
   where pr.projectkey = p.projectkey

ps:timestamp 是oracle对date的扩展,其度量精度比date类型更高。

case when 在这条语句中有2个形态,注意语法上些许差别。

上面没有更新commobject表中parent,后面用一条语句更新一下,即根据一张表的数据更新另外一张表相关字段。

--temp22 是一张临时表 
update commobject t

   set t.parent = (select s.pk2 from temp22 s where s.pk0 = t.id)

 where t.id in (select s.pk0 from temp22 s)

mondrian用到的维度表是偏平化结构,所以要去掉非末级节点:


delete   from c1_dim_account  c1 where c1.id in (

select p.projectkey+500000 pk0 from dim_chargeproject p where p.isleaf=0);

 到此,模拟维度数据准备完毕。

 

其他开发配置:

我们项目何vue前端,采取json交换,因此,引入了json相关jar,json消息,我们需要进行格式化封装,沿用我们原有项目格式,又是一番copy,解决问题。

测试vue 前端和后端服务连接,上一段测试代码,ok! 测试代码如下:

<template>
  <div id="vue_olap_showData">
    <div>
      <el-button type="primary" @click="get_olap_showData">读取后台数据</el-button>
    </div>
    <div class="olapResult" v-html="olapData"></div>
  </div>
</template>

<script  type="text/javascript">
import olapShowData from "@/api/olap/olap_showData.js";
export default {
  data() {
    return {
      olapData: ""
    };
  },
  methods: {
    get_olap_showData() {
      olapShowData.olapShowData().then(res => {
        this.olapData = res.data;
      });
    }
  }
};
</script>

<style lang='scss'>
.olapResult {

  td {
    font-size: 12px;
    border-left: solid 1px silver;
    border-right: none;
    border-top: none;
    border-bottom: solid 1px silver;
    text-align: right;
    width: 105px;
    height: 25px;
  }
}
//flex 高度控制的问题,还有点模糊,先放着
.vue_olap_showData {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}


</style>

效果如下图:

 

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页