为了学习lagom,我创建了一个简单的应用程序,其中包含一些简单的持久实体和一个持久读取端(根据官方文档,使用cassandra(
官方文档包含有关模型演变的部分,描述了如何更改模型。然而,在阅读方面没有提到进化。
假设我有一个名为Item
的实体,带有一个ID
和一个name
,并且读取端创建了一个类似CREATE TABLE IF NOT EXISTS items (id TEXT, name TEXT, PRIMARY KEY (id))
我现在想更改项目以包含描述。这对于持久实体来说是微不足道的,但读取端也必须更改。
我可以看到几种方法(也许(实现这一目标:
- 使用模型演化工具(如 Liquibase(或 Play Evolutions 来更改读取端表。
- 以某种方式在迁移模型的
createTables
中包含update table
语句 - 创建包含附加信息的附加表,并保留旧表而不进行修改
哪种方法最合适?还有更好的吗?
恕我直言,创建一个新表并删除旧表也是一种选择。 这很简单,就像修改您的"创建表"命令("创建表mytable_v2..."和"删除表 mytable..."(并更改偏移量名称并修改事件处理程序。
override def buildHandler( ): ReadSideProcessor.ReadSideHandler[MyEvent] = {
readSide.builder[MyEvent]("myOffset") // change it to "myOffset_v2"
...
}
这会导致重播所有事件,并从头开始重建读取端表。如果当前表非常大,这可能不是一个选项,因为重组可能会持续很长时间。
关于@erip所说的内容,我认为在您的阅读端表中添加新列是完全正常的。假设此表中有很多记录,其中包含所有实体的列表,并且您希望根据某些条件检索实体列表,因此您需要在 where 子句中包含一些列。检索所有实体的列表并询问每个实体是否符合标准根本不是一种选择 - 它可能效率非常低,因为它需要更多的时间、内存和网络使用。
读取端的要点是具体化来自服务中服务事件流的实体状态更改的视图。在这方面,作为服务控制者,您可以决定订阅者要了解的重要内容。这是通过创建具有防损层(或 ACL(的读取端来处理的。
通常,您的订阅者将订阅不应经历演变的 API 事件。您的内部事件(或 impl 事件(可能需要发展;因此,应该有一个从 impl 到 API 的转换。
这就是为什么在设计之前非常仔细地考虑您的域名非常重要的原因:您确实需要确定订阅者需要了解的内容。在描述的情况下,我觉得订阅者不太可能需要(或想要!(了解这一点。