6

I have a lot of existing data in my database already, and want to develop a points mechanism that computes a score for each user based on what actions they do.

I am implementing this functionality in a pluggable way, so that it is independent of the main logic, and relies on Spring events being sent around, once an entity gets modified.

The problem is what to do with the existing data. I do not want to start collecting points from now, but rather include all the data until now.

What is the most practical way to do this? Should I design my plugins in such a way as to provide for an index() method, which will force my system to fetch every single entity from the database, send an EntityDirtyEvent, to fire the points plugins, for each one, and then update it, to let points get saved next to each entity. That could result in a lot of overhead, right?

The simplest thing would be to create a complex stored procedure, and then make the index() call that stored procedure. That however, seems to me like a bad thing either. Since I will have to write the logic for computing the points in java anyway, why have it once again in SQL? Also, in general I am not a fan of splitting business logic into the different layers.

Has anyone done this before? Please help.

4

5 回答 5

4

首先让我们区分实现策略和业务规则。

由于您已经拥有数据,请考虑直接从数据中获取结果。这形成了数据域模型。设计数据模型以存储所有数据。然后,创建一组查询、视图和存储过程来访问和更新数据。

一旦有了这些视图,就可以使用 Spring JDBC Template 等数据访问库来获取这些数据并将它们表示为 Java 对象(列表、地图、人员、点表等)。

不管系统的上层发生了什么,到目前为止你已经完成的事情并没有太大的变化。这称为模型。

然后,开发一个规则库或逻辑实现,以确定在什么输入、用户操作、数据条件或所有其他条件下需要什么数据。在数学意义上,这就像一个矩阵。在编程意义上,这将是一组逻辑语句。如果 this and this and this 为真,则获取此数据,否则获取该数据,等等。这包含您系统中的逻辑。因此它被称为“控制器”。

不要将此逻辑移动到查询/存储过程/视图中。

然后最后为此开发一个前端或“控制台”。在最简单的情况下,开发一个控制台输入系统,它接受一个 .. 并显示一组结果。这是您对系统的“视图”。

您最终可以将视图开发为 Web 应用程序。上面的命令行视图仍然可以以 Restful API 服务器的形式存在。

于 2012-07-27T16:02:02.957 回答
2

你似乎正朝着正确的方向前进。您知道您希望您的“积分”事物与主应用程序分离。由于暗示您已经在使用休眠(通过标签!),您可以利用休眠事件系统(参见此处的第 14.2 节)。根据系统的大小/复杂性,您可以在此处插入积分计算(如果它不是大型/复杂系统),或者您可以发布自己的事件以供任何正在侦听的软件接收。

任何一种设计方法的要点都是既不知道也不关心您的点计算。如果您像我猜测的那样尝试创建一个相当通用的插件机制,那么您可以从这个连接点将您自己的事件发布到该系统。然后,如果您在给定的安装/设置中没有插件,则没有人获取/处理事件。如果您在另一个安装/设置中有多个插件,那么它们每个都可以根据收到的事件决定他们需要进行的处理。在“积分插件”的情况下,它会计算它的积分值并存储它。不需要存储过程....

于 2012-08-07T12:41:59.240 回答
2

我认为这里需要考虑一个问题:据我所知,数据库中有大量数据,因此仅创建一种机制来计算积分系统的想法可能不是最好的方法。

事实上,如果您不想开始收集积分但包含所有数据,您必须处理和计算您现在拥有的信息。是的,您第一次运行它可能会产生开销,但正如您所说,您需要计算此数据。

另一方面,您可以包含另一种机制来处理实体中的更改并启动能够计算适用于此特定修改的新指向差异的不同进程。

因此,您可以使用一种服务来负责计算指向系统,一种用于单个实体,另一种可能需要更长的时间才能完成,能够计算全局点。甚至,如果您不需要实时计算,您可以创建一个计划作业来负责启动它。

最后,我知道将业务逻辑拆分为两层(Db + Java)不是一个好方法,但有时需要这样做,例如,如果您需要快速回复最终与许多注册表一起使用的请求. 我发现在某些情况下,除了将业务逻辑添加到数据库(作为存储过程等)来管理大量数据并将最终结果返回给浏览器客户端(例如:特定时间的计算过程)之外,别无选择)。

于 2012-08-06T11:16:48.060 回答
2

您正在尝试完成“引导”。您选择的方法应取决于点计算的复杂程度。如果存储过程或普通更新语句是最简单的解决方案,那就这样做。

如果计算很复杂,请编写一个批处理作业来加载现有数据,可能首先将其排序,然后触发与该数据对应的事件,就好像它们刚刚发生一样。处理事件的代码应该与处理未来事件的代码完全相同,因此除了批处理作业本身之外,您无需编写任何其他代码。

因为你只打算运行这个东西一次,所以选择最简单的解决方案,即使它又快又脏。

于 2012-08-07T12:10:11.390 回答
1

有两种不同的方式。一是您已经知道 - 轮询数据库以获取更改的数据。在这种情况下,您可能会在没有更改的情况下访问数据库,并且可能会减慢您的流程。

第二种方法 - 每当数据库发生更改时,数据库将触发该事件。您可以使用 CDC(更改数据捕获)。它将最小化开销。

您可以在Spring Integration中寻找更多选项

于 2012-08-08T06:48:44.090 回答