前一段时间,我遇到了一个我目前的数据结构的问题,其中任何影响时间,日期或价格的更改将影响其他相关的财务记录,日期的预订列表等.
我当时的解决方案是创建一个修改表来跟踪对预订所做的任何更改.然后,每当预订模型被要求退回预订时,它将添加修改(在afterFind()蛋糕回调),并提供最新版本的预订,这样的话(借口绘画):
当您要求预订模式返回预订#1234时,此方法工作正常.它返回最新的预订表示,包括所有修改(彼此分层),包括包含所有修改的数组和原始预订数据供参考.
我的问题是,我最近意识到,我需要能够使用自定义条件查询此模型,如果其中一个条件在其中一个修改中实现,则结果将不匹配,因为模型正在搜索原始记录而不是终于呈现的记录.示例,我查询模型返回abc是蓝色(不是灰色)的行:
在该示例中,模型直接看到abc为蓝色的行的原始数据,并且不返回此结果,因为蓝色值位于在找到原始结果之后附加的修改.
我现在所做的是将预订模型的beforeFind()回调查询到寻找符合给定条件的修改,加入预订以确保任何其他条件仍然匹配.当它返回上面的示例中的蓝色时,它将该结果作为类属性存储在数组中,并继续使用常规的find(),但不包括预订的ID被返回(因为我们已经找到更新的验证).然后,它们将它们合并在一起,再次对afterFind()进行排序.
这是有效的,虽然这是一个更长的时间,我希望.
毕竟,我已经意识到,在这个应用程序的其他部分,有手动加入预订表和搜索预订的模型.所以现在我需要一种方法可以将所有这些手动连接的修改整合到MySQL中,而不影响原始数据,最好不要改变我的代码太多.
我的想法是,我需要删除手动联接,并建立一个模型关联.当我查询说客户型号有多少预订(对每个预订应用修改)时,预订模型的beforeFind()和afterFind()是否仍然运行?
我的另一个选择是通过删除修改中可能包含的任何标准,从MysqL返回更多的行,然后使用PHP根据搜索条件过滤结果.这个选项吓倒了我一点,因为结果集有可能是巨大的没有这个标准…
如何实现这个数据结构?我的主要要求仍然是我不想更改原始的预订记录,而是添加修改记录,但是我需要能够通过模型来查询预订(包括修改).
我想尝试尽可能多地保持这种整合的背景,所以我不必经历我的整个应用程序来更改n个查询,如下所示:
$get_blue = $this->Booking->find('all',array( 'conditions' => array( 'Booking.abc' => 'blue' ) ));
我想要隐含地包含对预订的任何修改,以便在上述查询中返回最新的预订.
$get_transactions_on_blue_bookings = $this->Transaction->find('all',array( 'joins' => array( array( 'table' => 'sql_bookings_table',// non-standard Cake format,I know - it's an example 'alias' => 'Booking','type' => 'LEFT','conditions' => 'Booking.booking_id = Transaction.booking_id' ) ),'conditions' => array( 'Booking.abc' => 'blue' ) ));
您可以看到,上述查询将不包括我上面的MSPaint示例中的修改,因为它是手动加入sql中的表(修改集成在Booking模型的before和afterFind()回调函数中).
对此的任何帮助将不胜感激.
编辑
我知道这已经够久了,但是我想我补充说,我想跟踪这些变化而不是更新原始记录的原因是财务方面不能改变,因为它会影响报告.
到目前为止,我可以看到的最简单和最简单的解决方案是在所有情况下直接对原始预订进行修改,除非它会影响财务信息,这仍然被修改(因为我目前不需要根据这个信息进行搜索) ).
相比之下,我们使用的没有时间特征的传统数据库可以称为当前数据库.
在当前数据库中,如果您尝试实现时间支持,则可能会通过不同的方法在许多方面失败:
>一表方法.当您需要进行修改时,您可以对原始记录进行更新,除非您有某种本地触发/审计逻辑,否则历史记录不存在.即使你有一个审计/更改日志,你必须做一些丑陋的挖掘重建变更历史.
>双表方法.而不是就地进行修改,您可以将数据分成两个表,一个是基数/原始记录(例如预订),另一个表用于更改/修改/增量.那么至少你保留原始数据,但是再次需要编写复杂的逻辑来查看原始数据并进行修改.如果您只想要应用一些修改,它会变得更糟.
>预先计算的结果表方法.您保留3个或更多表:基本记录,修改以及尝试始终具有结果的表(保持最新的基本修改).祝你好运,编写触发器和程序来做这个计算,每当你做INSERT,而天堂帮助你,如果需要UPDATE或DELETE.该设置是脆弱的,可能会失去同步,例如死锁和回滚.如果您不使用触发器/程序在数据库中执行此操作,则可以尝试在应用程序代码中实现其计算结果,但运行良好,并且可能会在多线程消费者中受到困扰.而且,您仍然无法轻松访问结果,只能进行一些修改.