最代码网站中关于动态表event的设计思路
原文:最代码网站中关于动态表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, "<a href='/user/n/" + _user.getName() + ".htm'>" + _user.getName() + "</a>"); 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显示层转换核心代码:
<#switch event.eventRule.type> <#case event_type_rule_post_create> <@event_post_macro event.target/> <#break> <#case event_type_rule_project_create> <@event_project_macro event event.target/> <#break> <#case event_type_rule_project_view> <#case event_type_rule_project_collect> <#case event_type_rule_project_reward> <@event_project_macro event event.source/> <#break> <#case event_type_rule_comment_create> <@event_comment_macro event event.target/> <#break> <#case event_type_rule_answer_create> <@event_answer_macro event event.target/> <#break> <#case event_type_rule_answer_get> <#case event_type_rule_answer_been_set_perfect> <@event_answer_macro event event.source/> <#break> <#case event_type_rule_mention_comment> <@event_comment_macro event event.target/> <#break> <#case event_type_rule_mention_post> <@event_post_macro event.source/> <#break> </#switch>
比如其中一种event type的freemarker macro代码如下:
<!--event post--> <#macro event_post_macro post> <div class="content margin_top5"> ${post.contentExt} <span class="comments_count"> <a target="_blank" href="/mood/${post.id}/comment.htm" rel="nofollow"><img src="/static/imghw/default1.png" data-src="/resource/img/comment.gif" class="lazy" alt="${post.thirdSort}个评论"> ${post.thirdSort}</a> </span> </div> </#macro>
这样的设计符合高内聚低耦合的设计思路,未来可以根据业务实现无限扩张,当然代价就是event表越来越大,但可以通过分库分表来分担压力,大家可以参考下,有好的意见可以留言。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック

仮想マシンを作成するときに、ディスクの種類を選択するように求められます。固定ディスクまたはダイナミック ディスクを選択できます。固定ディスクを選択した後でダイナミック ディスクが必要であることに気付いた場合、またはその逆の場合はどうすればよいでしょうか? いいですね!一方をもう一方に変換できます。この記事では、VirtualBox 固定ディスクをダイナミック ディスクに、またはその逆に変換する方法を説明します。ダイナミック ディスクは、最初は小さいサイズですが、仮想マシンにデータを保存するにつれてサイズが大きくなる仮想ハード ディスクです。ダイナミック ディスクは、必要なだけのホスト ストレージ スペースのみを使用するため、ストレージ スペースを節約するのに非常に効率的です。ただし、ディスク容量が増加すると、コンピュータのパフォーマンスがわずかに影響を受ける可能性があります。仮想マシンでは固定ディスクとダイナミック ディスクが一般的に使用されます

4月17日のニュースによると、HMDは有名なビールブランドのハイネケンとクリエイティブ企業のボデガと提携して、ユニークな折りたたみ式携帯電話「The Boring Phone」を発売した。この携帯電話は、デザインの革新性だけでなく、機能面でも自然に立ち返り、人々を本当の人間関係に戻し、友人と飲む純粋な時間を楽しむことを目指しています。退屈な携帯電話は、ユニークな透明なフリップデザインを採用し、シンプルでありながらエレガントな美しさを示しています。内部には 2.8 インチ QVGA ディスプレイ、外部には 1.77 インチ ディスプレイが装備されており、ユーザーに基本的な視覚的インタラクション エクスペリエンスを提供します。写真に関しては、3,000万画素のカメラしか搭載されていませんが、日常の簡単な作業には十分です。

4月26日のニュースによると、ZTEの5GポータブルWi-Fi U50Sが正式に販売され、価格は899元からとなっている。外観デザインに関しては、ZTE U50S ポータブル Wi-Fi はシンプルでスタイリッシュで、持ちやすく、梱包しやすいです。サイズは159/73/18mmで持ち運びが簡単で、いつでもどこでも5G高速ネットワークを楽しむことができ、妨げられないモバイルオフィスとエンターテインメント体験を実現します。 ZTE 5G ポータブル Wi-Fi U50S は、最大 1800Mbps のピーク レートの高度な Wi-Fi 6 プロトコルをサポートし、Snapdragon X55 高性能 5G プラットフォームを利用して、ユーザーに非常に高速なネットワーク エクスペリエンスを提供します。 5G デュアルモード SA+NSA ネットワーク環境と Sub-6GHz 周波数帯域をサポートするだけでなく、測定されたネットワーク速度は驚異的な 500Mbps に達することもあり、これは簡単に満足できます。

4 月 3 日のニュースによると、Taipower の次期 M50 Mini タブレット コンピューターは、豊富な機能と強力なパフォーマンスを備えたデバイスです。この新しい 8 インチの小型タブレットは 8.7 インチ IPS スクリーンを搭載しており、ユーザーに優れた視覚体験を提供します。メタルボディのデザインは美しいだけでなく、耐久性も高めています。パフォーマンスの面では、M50Mini には、2 つの A75 コアと 6 つの A55 コアを備えた Unisoc T606 8 コア プロセッサが搭載されており、スムーズで効率的な実行エクスペリエンスを保証します。同時に、このタブレットには6GB + 128GBのストレージソリューションも装備されており、8GBのメモリ拡張をサポートしており、ストレージとマルチタスクに対するユーザーのニーズを満たします。バッテリー寿命の点では、M50Mini は 5000mAh バッテリーを搭載しており、Ty をサポートしています。

7月12日のニュースによると、Honor Magic V3シリーズは本日正式にリリースされ、新しいHonor Vision Soothing Oasisアイプロテクションスクリーンを搭載しており、スクリーン自体は高スペックで高品質であると同時に、AIアクティブアイプロテクションの導入も先駆けとなっています。テクノロジー。近視を軽減する伝統的な方法は「近視メガネ」であると報告されています。近視メガネの度数は均等に分散され、視野の中心領域は網膜上に結像されますが、周辺領域は網膜の後ろに結像されます。網膜は像が遅れていると認識し、眼軸方向の成長を促進し、その度数が深くなります。現在、近視の進行を軽減する主な方法の 1 つは、「デフォーカス レンズ」です。中央領域は通常の度数で、周辺領域は光学設計の隔壁によって調整され、周辺領域の像が収まります。網膜の前。

仕事では、ppt は専門家がよく使用するオフィス ソフトウェアです。完全な ppt には適切な終了ページが必要です。専門的な要件が異なると、ppt 作成の特性も異なります。エンドページの制作について、どうすればより魅力的にデザインできるでしょうか? pptの終了ページのデザイン方法を見てみましょう! pptの終了ページのデザインはテキストとアニメーションの点で調整でき、ニーズに応じてシンプルまたは華麗なスタイルを選択できます。次に、革新的な表現方法を使用して、要件を満たす ppt の終了ページを作成する方法に焦点を当てます。それでは、今日のチュートリアルを始めましょう。 1. 終了ページの制作は、画像内の文字であれば何でも構いませんが、終了ページで重要なのは、私のプレゼンテーションが終了したことを意味することです。 2. これらの言葉に加えて、

Linux オペレーティング システムでファイルを操作するには、開発者がファイル、コード、プログラム、スクリプトなどを効率的に作成および実行できるようにするさまざまなコマンドとテクニックを使用する必要があります。 Linux 環境では、拡張子「.a」を持つファイルは静的ライブラリとして非常に重要です。これらのライブラリはソフトウェア開発において重要な役割を果たし、開発者が複数のプログラム間で共通の機能を効率的に管理および共有できるようにします。 Linux 環境で効果的なソフトウェア開発を行うには、「.a」ファイルの作成方法と実行方法を理解することが重要です。この記事では、Linux の「.a」ファイルのインストールと構成方法を包括的に紹介します。Linux の「.a」ファイルの定義、目的、構造、作成および実行方法について見てみましょう。 Lとは何ですか

7月29日のニュースによると、Honor X60i携帯電話は本日正式に発売され、価格は1,399元からとなっている。デザインの面では、Honor X60i 携帯電話は、中央に穴があり、四辺すべてにほぼ境界のない超狭い境界線を備えたストレート スクリーン デザインを採用しており、視野が大幅に広がります。 Honor X60i パラメータ ディスプレイ: 6.7 インチ高解像度ディスプレイ バッテリー: 5000mAh 大容量バッテリー プロセッサー: Dimensity 6080 プロセッサー (TSMC 6nm、2x2.4G A76+6x2G A55) システム: MagicOS8.0 システム その他の機能: 5G 信号強化、スマートカプセル、画面下指紋認証、デュアルMIC、ノイズリダクション、知識Q&A、撮影機能:背面デュアルカメラシステム:5000万画素メインカメラ、200万画素補助レンズ、フロントセルフィーレンズ:800万画素、価格:8GB
