原文:最代码网站中关于动态表event的设计思路 为了能将最代码整站用户的操作都展现出来,需要设计一种动态类型,既可以根据业务无限扩展,也可以指定某些用户行为是可以产生多少牛币交换的,这样就在原先javaniu的零散的表设计基础上抽象出event表 表结构如
原文:最代码网站中关于动态表event的设计思路
为了能将最代码整站用户的操作都展现出来,需要设计一种动态类型,既可以根据业务无限扩展,也可以指定某些用户行为是可以产生多少牛币交换的,这样就在原先javaniu的零散的表设计基础上抽象出event表
表结构如下:
create table `javaniu_event` ( `id` bigint(20) unsigned not null auto_increment, `create_time` datetime not null, `update_time` datetime default null, `event_rule_id` bigint(20) not null default '0' comment '用户注册\r\n下载代码\r\n浏览分享\r\n浏览寻求\r\n收藏分享\r\n收藏寻求\r\n浏览活动\r\n追加悬赏\r\n加入活动\r\n拜师\r\n关注用户\r\n发表心情\r\n发表寻求\r\n评论寻求\r\n评论代码\r\n上传代码\r\n下载代码\r\n分享代码\r\n关注用户\r\n浏览分享\r\n浏览寻求\r\n管理员删除代码\r\n收藏分享\r\n收藏寻求\r\n获取勋章\r\n拜师傅\r\n发起活动\r\n浏览活动\r\n加入活动\r\n追加悬赏\r\n连续一周发表心情\r\n用户周贡献排行\r\n用户月贡献排行\r\n用户年贡献排行\r\n代码下载周排行\r\n代码下载月排行\r\n代码下载年排行', `user_id` bigint(20) not null default '0', `source_user_id` bigint(20) not null default '0', `source_id` bigint(20) not null default '0', `target_id` bigint(20) not null default '0', `status` int(2) not null default '0' comment '-1删除0待审核2正常', `type` int(2) not null default '0', primary key (`id`), key `create_time` (`create_time`), key `userid_status` (`user_id`,`status`), key `event_rule_id_source_id` (`event_rule_id`,`source_id`), key `event_rule_id_status` (`event_rule_id`,`status`), key `type_source_id` (`type`,`source_id`)) engine=innodb default charset=utf8
关联表event_rule可以指定牛币规则及其动态显示信息,结构如下:
create table `javaniu_event_rule` ( `id` bigint(20) unsigned not null auto_increment, `create_time` datetime not null, `update_time` datetime default null, `type` int(1) not null comment '注册+1\r\n发表心情+1\r\n连续一周发表心情+5\r\n分享代码+1\r\n分享代码被下载+n(n为分享者者自定义牛币)\r\n寻求代码-2\r\n上传代码+1\r\n上传代码被下载+1\r\n代码被设为最佳+n(n为寻求者者自定义牛币)\r\n删除代码-1\r\n无效寻求-2\r\n无效代码-2\r\n管理员奖赏+n\r\n管理员惩罚-n\r\n周top10+5\r\n月top10+10\r\n年top10+100\r\n信息完善+1\r\n包月vip+100\r\n师傅赠送+n牛币\r\n授予徽章+5牛币\r\n', `name` varchar(100) not null, `niubi` int(11) not null, `extend_json` varchar(1000) not null, primary key (`id`)) engine=innodb default charset=utf8
event的用户行为数据模型抽象如下:
模型一:用户a通过事件x产生动态0=user_id_a 0 0 0
a=>x=>0
模型二:用户a通过事件x产生产生用户a的数据1=user_id_a 0 0 1
a=>x=>1
模型三:用户a通过事件x对用户b的数据1产生用户a的数据2=user_id_a b 1 2
a=>x+b+1=>2
模型四:用户a通过事件x对用户b的数据1产生动态0=user_id_a b 1 0
a=>x+b+1=>0
模型五:用户a通过事件x对用户b产生动态0=user_id_a b 0 0
a=>x+b=>0
排列组合:
user_id source_user_id source_id target_id
user_id
user_id source_user_id
user_id source_user_id source_id
user_id source_user_id source_id target_id
这样就囊括了所有会出现的用户event,只要在java层做业务转换即可:
最核心的event数据转换java类源码:
package com.zuidaima.core.service.impl; private void setsourceandtarget(event event, eventrule _eventrule) { try { eventrule eventrule = new eventrule(); eventrule.setcreatetime(_eventrule.getcreatetime()); eventrule.setextendjson(_eventrule.getextendjson()); eventrule.setid(_eventrule.getid()); eventrule.setname(_eventrule.getname()); eventrule.setniubi(_eventrule.getniubi()); eventrule.settype(_eventrule.gettype()); eventrule.setupdatetime(_eventrule.getupdatetime()); baseentity source = null; baseentity target = null; long sourceid = event.getsourceid(); long targetid = event.gettargetid(); jsonobject extend = eventrule.getextend(); extend = eventrule.getextend(); string description = (string) extend.get(description); string _description = null; answer answer = null; project project = null; switch (eventrule.gettype()) { case moduleconstants.event_type_rule_project_create: case moduleconstants.event_type_rule_project_delete_by_user: case moduleconstants.event_type_rule_project_delete_by_admin: case moduleconstants.event_type_rule_project_view: case moduleconstants.event_type_rule_project_collect: case moduleconstants.event_type_rule_project_reward: if (sourceid > 0) { source = projectservice.findonebyid(sourceid); } if (targetid > 0) { target = projectservice.findonebyid(targetid); } project = (project) target; if (source != null) { project = (project) source; } if (project == null) { return; } _description = string.format( description, moduleconstants.project_type_desc_map.get( project.gettype()).getdesc()); break; case moduleconstants.event_type_rule_post_create: case moduleconstants.event_type_rule_post_delete_by_user: case moduleconstants.event_type_rule_post_delete_by_admin: if (sourceid > 0) { source = postservice.findonebyid(sourceid); } if (targetid > 0) { target = postservice.findonebyid(targetid); } post post = (post) target; if (source != null) { post = (post) source; } _description = string.format(description, moduleconstants.post_type_desc_map.get(post.gettype())); break; // case moduleconstants.event_type_rule_group_create://暂时没有这种动态 case moduleconstants.event_type_rule_group_join_in: case moduleconstants.event_type_rule_group_delete_by_user: // case // moduleconstants.event_type_rule_group_delete_by_admin://暂时没有这种动态 if (sourceid > 0) { source = groupservice.findonebyid(sourceid); } if (targetid > 0) { target = groupservice.findonebyid(targetid); } group group = (group) source; _description = string .format(description, moduleconstants.group_type_desc_map.get(group .gettype())); break; case moduleconstants.event_type_rule_comment_create: case moduleconstants.event_type_rule_comment_delete_by_user: case moduleconstants.event_type_rule_comment_delete_by_admin: target = commentservice.findonebyid(targetid); comment comment = (comment) target; int commenttype = comment.gettype(); if (commenttype == moduleconstants.comment_type_answer) { source = answerservice.findonebyid(sourceid); answer = (answer) source; project = (project) answer.gettarget(); _description = string.format( description, moduleconstants.project_type_desc_map.get( project.gettype()).getdesc()); } else if (commenttype == moduleconstants.comment_type_project) { source = projectservice.findonebyid(sourceid); project = (project) source; _description = string.format( description, moduleconstants.project_type_desc_map.get( project.gettype()).getdesc()); } else if (commenttype == moduleconstants.comment_type_post) { source = postservice.findonebyid(sourceid); post = (post) source; _description = string.format(description, moduleconstants.post_type_desc_map.get(post .gettype())); } else { } break; case moduleconstants.event_type_rule_answer_create: case moduleconstants.event_type_rule_answer_been_set_perfect: source = projectservice.findonebyid(sourceid); target = answerservice.findonebyid(targetid); project = (project) source; _description = string.format( description, moduleconstants.project_type_desc_map.get( project.gettype()).getdesc()); break; case moduleconstants.event_type_rule_answer_get: case moduleconstants.event_type_rule_answer_delete_by_user: case moduleconstants.event_type_rule_answer_delete_by_admin: source = answerservice.findonebyid(sourceid); answer = (answer) source; project _project = (project) answer.gettarget(); _description = string.format( description, moduleconstants.project_type_desc_map.get( _project.gettype()).getdesc()); break; case moduleconstants.event_type_rule_reputation_create: if (sourceid > 0) { source = reputationservice.findonebyid(sourceid); } if (targetid > 0) { target = reputationservice.findonebyid(targetid); } break; case moduleconstants.event_type_rule_user_follow: source = userservice.findonebyid(sourceid); user _user = (user) source; _description = string .format(description, + _user.getname() + ); break; case moduleconstants.event_type_rule_mention_comment: target = commentservice.findonebyid(targetid); comment = (comment) target; commenttype = comment.gettype(); if (commenttype == moduleconstants.comment_type_answer) { source = answerservice.findonebyid(sourceid); answer = (answer) source; project = (project) answer.gettarget(); _description = string.format( description, moduleconstants.project_type_desc_map.get( project.gettype()).getdesc()); } else if (commenttype == moduleconstants.comment_type_project) { source = projectservice.findonebyid(sourceid); project = (project) source; _description = string.format( description, moduleconstants.project_type_desc_map.get( project.gettype()).getdesc()); } else if (commenttype == moduleconstants.comment_type_post) { source = postservice.findonebyid(sourceid); post = (post) source; _description = string.format(description, moduleconstants.post_type_desc_map.get(post .gettype())); } else { } break; case moduleconstants.event_type_rule_mention_post: source = postservice.findonebyid(sourceid); break; default: _description = description; } extend.put(description, _description); eventrule.setextend(extend); eventrule.setextendjson(extend.tostring()); event.seteventrule(eventrule); event.setsource(source); event.settarget(target); } catch (exception e) { logger.error(fail to setsourceandtarget event: + event); } }
freemarker显示层转换核心代码:
比如其中一种event type的freemarker macro代码如下:
${post.contentext} ${post.thirdsort}
这样的设计符合高内聚低耦合的设计思路,未来可以根据业务实现无限扩张,当然代价就是event表越来越大,但可以通过分库分表来分担压力,大家可以参考下,有好的意见可以留言。