olap分析平台的设计与实现(二十)- 维度管理开发杂记

维度管理:核心操作当然是维度成员的增删改。维度管理分为维度管理与维度成员管理2部分:维度管理,\维度成员管理:

和普通增删改略有差别,维度管理CRUD的时候,除了增加维度字典相关数据,还应该维持olap相关维度、事实表。

后端开发还好,前端熟悉了一下ant Form表单,Modal调用的相关内容。

(共享维设置)  

( 操作符)

在后端,共享维度的处理就是“维度名字+(共享)”形成的。

memberName += Constants.shareMemberMarking;

共享维度 只用插入字典表,不用插入olap维度表!

分为维度管理与维度成员管理2部分:维度管理,\维度成员管理:

一个维度成员 可以在多个分析模型当中,即一个维度成员可以在多个立方体(cube)当中,维度成员和立方体是1-*的关系;

维度区分是否多层级 isMultiLevelMember:是多层级成员

子维度范围  父维度范围:

自定义的维度成员,和一个或者多个特定的cube相关联,我们给cube定义了modtype,其实就是按位给cube一个编号,

001 是cube1;

010是cube2;

100是cube3 

 

一个维度成员能在哪些cube当中用,看used_In,把每个cube的mod_type和used_in进行位运算!

如何理解isleafIncube?(待补充)

计算成员的定义:对应mdx的with member

计算成员必须校验,我们进行了2个校验:

校验的代码如下:

	private static String testFormulaMdx(String formula, CDimension dimension,
			DimMember member, CCube bgCube) {
		String formulaMemberName = "[" + dimension.getName() + "].[VALIDATE_MEMBER]";
		String str="WITH MEMBER " + formulaMemberName + " AS (" + formula
				+ ") SELECT " + formulaMemberName + " ON COLUMNS FROM ["
				+ bgCube.getName() + "]";
		return str;
	}

保存新增加维度成员到数据库:

增加一般维度,主要有如下操作:

  1. 增加字典表
  2. 增加维度表

要保存如下信息:

  1. 修改父节点信息
  2. 新增加的子节点信息
  3. 对应的计算公式
  4. 对应的别名表
  5. 成员聚合运算符信息
  6. 对应的olap引擎需要的维度表:
  7. 度别名表的处理:

一个维度 有多个对应的别名  放到单独的表当中ALIAS_TALBE ,

ALIAS_TALBE 就2个字段:Id、name

共享维度是给多个立方体共用的维度 不能和已有的维度重名

parent Member

cuurent Member

formular

formular表仅仅有2个字段:

  1. id:  也是维度成员id
  2. formularString

和维度成员对应的别名表:

一个维度成员,可以对应多个别名?aliases如:[["600","default"],["602","测试别名"]]

维度管理前端:

首先是选中维度类型

然后是选中相关维度成员节点:

{
    "key": 600077,
    "id": "600077",
    "text": "rrr1000",
    "checked": false,
    "parentId": "600069",
    "hasParent": true,
    "hasChildren": false,
    "btn": false,
    "levelnum": 0
}

选择维度成员的时候,弹出模态框:

1、设置模态框可见性属性(DimForm state)

2、传递值给Modal(通过prop)

成员公式:

react中,获取iinput值的方法,和传统js略有差异,参见下文

ps:react中获取input输入框内容的两种方法

后台服务必须有这样的方法:根据维度id,查询所有的维度成员!

构建公式-->构建维度成员

构建祖先成员的集合,构建children,这个是在构造缓存的时候,就完成了的。

String formatName=BusinessMethods.formatMember(memberName, generation);?再有后端向服务端吐数据之前,就搞这个

保存:

	private synchronized void saveFormulaMember(final String formula, final DimMember pMember,
			final DimMember ...) {
		
		DBHelper.update(pMember);
		DBHelper.save(cMember);
		FormulaMember formulaMember = new FormulaMember();
		formulaMember.setId(cMember.getMemberId());
		formulaMember.setFormula(formula);
		DBHelper.save(formulaMember);
	}

删除维度成员:

最一般成员主要删除动作为,

  1. 删除事实表:如:delete from c1_fact1;
  2. 删除和事实表关联的维度表:delete from C1_DIM_YEAR where 1=1  and ID=?
  3. 删除数据字典表:

        delete  from COMMOBJECT o where o.id=601422

         delete from C_YEAR  where id=601422

一个是删除维度表中维度信息,一个是删除mondrian 维度表中的相关数据

能删除最顶级维度成员(通过检查代数)

删除维度成员本身及其关联的描述信息。(dimmember,description)

删除mondrian fact data与mondrian dim data;

删除成员操作信息

删除dim  alias

删除事实表:其实就是根据cube name & dimession Id,构造删除事实表中数据的的sql

删除维度信息的时候,由于维度成员继承了comm object,  他们的结构是:

ps:在Spring Data JPA中删除相同的事务后插入

React Hooks 入门教程二:useState使用、useEffect参数作用

React Hooks中父组件中调用子组件方法

动态构建mdx:

​
	/**
	 * 对外提供取得多维查询语句的接口
	 * @return 多维查询语句
	 */
	private  String getMdxString(FormShadow formShadow,int[] pageLayout){
		formShadow.getNoDetailMap().clear();
		formShadow.getShareMemberMap().clear();
		//CCube cube=formShadow.getCube();
		//String cubeName=cube.getName();
		//先简化问题  cube 名称给个固定值
		String cubeName="Col_trade_detail";
		List<List<List<DimMember>>> colMemberObjs = formShadow.getColMembers();
		List<List<List<DimMember>>> rowMemberObjs = formShadow.getRowMembers();
		List<List<DimMember>> pageMemberObjs = formShadow.getPageMembers();
		List<List<DimMember>> viewMemberObjs = formShadow.getViewMembers();
		String onCols = conMembers(colMemberObjs,formShadow);
		String onRows = conMembers(rowMemberObjs,formShadow);
		String onWheres = conWhereMembers(pageMemberObjs,viewMemberObjs,pageLayout,formShadow);
		String mdxString = makeMdxString(cubeName,onCols,onRows,onWheres);
		String withMemsStr = conWithMembers(colMemberObjs,rowMemberObjs,formShadow);
		if(withMemsStr!=null){
			mdxString = withMemsStr + mdxString;
			mdxString=replaceTempFormulaMember(mdxString, formShadow);
		}
		return mdxString;
	}

​

拼接子语句:

	/**
	 * 根据行/列成员对象连接成员字符串
	 * @param formShadow 
	 * @ param membersList  行成员/列成员对象的集合
	 * @return 连接成员字符串
	 */
	 private static String conMembers(List<List<List<DimMember>>> membersList0, FormShadow formShadow) {
		StringBuffer strBuffer=new StringBuffer();
		if (membersList0 != null&&membersList0.size()>0) {
			strBuffer.append("{");
			for (int k = 0; k < membersList0.size(); k++) {
				List<List<DimMember>> membersList = membersList0.get(k);
				if (membersList != null&&membersList.size()>0) {
					for (int i = 0; i < membersList.size(); i++) {
						strBuffer.append("{");
						List<DimMember> members=membersList.get(i);
						for (int j = 0; j < members.size(); j++) {
							DimMember member=members.get(j);
							CDimension dim=member.getDimension();
							String memberN=member.getNavigation();
/*							if(member.getHasChildren()==1){
								//非明细成员
								formShadow.getNoDetailMap().put(member.getMemberId(), dim.getId());
							}else{
								memberN=buildShareMember(member, dim, formShadow,memberN);
							}*/
							strBuffer.append(memberN);
							if (j != members.size() - 1) {
								strBuffer.append(",");
							}
						}
						strBuffer.append("}");
						if (i != membersList.size() - 1) {
							strBuffer.append("*");
						}
					}
				}
				if(k!=membersList0.size()-1){
					strBuffer.append(",");
				}
			}
			strBuffer.append("}");
		}
		return strBuffer.toString();
	}

构建with模块的事情,暂时放一下

构建各个分语句的时候,需要考虑祖先的层级,毕竟mdx 中,对元素描述需要全路径。

delete Dimession member(int dim,int memberId):

动态生成的8条语句:(其中七条是删除)

Hibernate: delete from C1_FACT where 1=1  and ACCOUNT=? 
Hibernate: delete from C1_DIM_ACCOUNT where 1=1  and ID=? 
Hibernate: select commobject0_.id as id1_16_0_, commobject0_.description as description2_16_0_, commobject0_.formula as formula3_16_0_, commobject0_.generation as generation4_16_0_, commobject0_.has_children as has_children5_16_0_, commobject0_.last_modified as last_modified6_16_0_, commobject0_.name as name7_16_0_, commobject0_.obj_type as obj_type8_16_0_, commobject0_.parent as parent9_16_0_, commobject0_.position as position10_16_0_, commobject0_1_.datastoretype as datastoretype1_12_0_, commobject0_1_.datatype as datatype2_12_0_, commobject0_2_.datastoretype as datastoretype1_15_0_, commobject0_2_.datatype as datatype2_15_0_, commobject0_2_.key as key3_15_0_, commobject0_2_.used_in as used_in4_15_0_, commobject0_3_.datastoretype as datastoretype1_11_0_, commobject0_3_.datatype as datatype2_11_0_, commobject0_3_.used_in as used_in3_11_0_, commobject0_4_.datastoretype as datastoretype1_27_0_, commobject0_4_.datatype as datatype2_27_0_, commobject0_4_.dim_type as dim_type3_27_0_, commobject0_4_.used_in as used_in4_27_0_, commobject0_6_.type as type1_5_0_, commobject0_6_.used_in as used_in2_5_0_, commobject0_7_.datastoretype as datastoretype1_14_0_, commobject0_7_.datatype as datatype2_14_0_, commobject0_8_.datastoretype as datastoretype1_6_0_, commobject0_8_.datatype as datatype2_6_0_, commobject0_8_.type as type3_6_0_, commobject0_8_.used_in as used_in4_6_0_, commobject0_9_.type as type1_2_0_, commobject0_9_.datastoretype as datastoretype2_2_0_, commobject0_9_.datatype as datatype3_2_0_, commobject0_9_.used_in as used_in4_2_0_, commobject0_10_.approval as approval1_7_0_, commobject0_10_.cube_id as cube_id2_7_0_, commobject0_10_.form_folder as form_folder3_7_0_, commobject0_10_.description as description4_7_0_, commobject0_10_.scale as scale5_7_0_, commobject0_10_.showway as showway6_7_0_, commobject0_11_.datastoretype as datastoretype1_4_0_, commobject0_11_.datatype as datatype2_4_0_, commobject0_11_.sign as sign3_4_0_, commobject0_12_.alias as alias1_3_0_, commobject0_12_.mod_type as mod_type2_3_0_, commobject0_12_.type as type3_3_0_, case when commobject0_1_.id is not null then 1 when commobject0_2_.id is not null then 2 when commobject0_3_.id is not null then 3 when commobject0_4_.id is not null then 4 when commobject0_5_.id is not null then 5 when commobject0_6_.id is not null then 6 when commobject0_7_.id is not null then 7 when commobject0_8_.id is not null then 8 when commobject0_9_.id is not null then 9 when commobject0_10_.id is not null then 10 when commobject0_11_.id is not null then 11 when commobject0_12_.id is not null then 12 when commobject0_.id is not null then 0 end as clazz_0_ from commobject commobject0_ left outer join c_scenario commobject0_1_ on commobject0_.id=commobject0_1_.id left outer join c_year commobject0_2_ on commobject0_.id=commobject0_2_.id left outer join c_period commobject0_3_ on commobject0_.id=commobject0_3_.id left outer join icp_customdim commobject0_4_ on commobject0_.id=commobject0_4_.id left outer join c_form_folder commobject0_5_ on commobject0_.id=commobject0_5_.id left outer join c_dim commobject0_6_ on commobject0_.id=commobject0_6_.id left outer join c_version commobject0_7_ on commobject0_.id=commobject0_7_.id left outer join c_entity commobject0_8_ on commobject0_.id=commobject0_8_.id left outer join c_account commobject0_9_ on commobject0_.id=commobject0_9_.id left outer join c_form commobject0_10_ on commobject0_.id=commobject0_10_.id left outer join c_currency commobject0_11_ on commobject0_.id=commobject0_11_.id left outer join c_cube commobject0_12_ on commobject0_.id=commobject0_12_.id where commobject0_.id=?
Hibernate: delete from c_account where id=?
Hibernate: delete from commobject where id=?
Hibernate:  DELETE FROM MEMBER_OPERATOR WHERE MEMBER_ID=? 
Hibernate:  DELETE FROM DIM_ALIAS WHERE MEMBER_ID=? 
Hibernate: DELETE FROM  ATTR_BASE_MEMBER WHERE BASE_MEMBER_ID=?

编辑的逻辑:

dimManagement要使用dim_info:

给dim_info传递dimession member Id,

在dim_info中获取维度成员信息

ps:Spring Boot(五):Spring Boot Jpa 的使用

ps:Spring Boot的事务管理注解@EnableTransactionManagement的使用

ps:在Spring Data JPA中删除相同的事务后插入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值