许多企业应用程序都将关系数据库作为对象的后端存储。 有些对象是不可变的,有些则不是。
当不可变对象依赖于mutable时,它应该提供适当的版本。
请参阅: 您有订单对象和客户对象。订单取决于客户。但订单永远不会改变。订单完成后发货客户更改了她的地址。 我怎么知道哪个地址用于运送? 我不想按顺序存储所有信息,因为它会使我的数据库非常规化。
答案是版本控制:订单应取决于具有特定版本的客户 。
这是用于共享库的想法(GAC,SxS,不同的.so版本等)。
但是如何在数据库中做到这一点? 将“version”字段添加到所有表和任何关系字段?这会增加我的数据库X2并使其纠结。
将此信息分开并存储在某处?
我相信必须有一个很好的解决方案。 你知道吗?
答案 0 :(得分:1)
我不太确定我理解这个问题。以你的客户和订单为例,你可以拥有
CREATE TABLE address (
address_id NUMBER PRIMARY KEY,
street VARCHAR2(100),
...
);
CREATE TABLE customer (
customer_id NUMBER PRIMARY KEY,
first_name VARCHAR2(100),
...
address_id NUMBER REFERENCES address( address_id )
);
CREATE TABLE orders (
order_id NUMBER PRIMARY KEY,
...
customer_id NUMBER REFERENCES customer( customer_id ),
address_id NUMBER REFERENCES address( address_id )
);
如果ADDRESS
是一流的表格,则ORDERS
和CUSTOMER
都可以引用特定地址。 CUSTOMER
可以引用客户的当前地址,ORDERS
可以引用订单被削减的地址,该地址可能是客户当时的地址,也可能是他们下订单的人的地址因为(我订的是母亲节送到母亲家的鲜花)。 ADDRESS
然后变为不可变,而不是更新ADDRESS
行,您只需使用新INSERT
执行ADDRESS_ID
并更新CUSTOMER
表中的行指向新的ADDRESS
。
如果要跟踪客户地址的历史记录,只需将address_id
移出customer
表并转移到具有某种排序的新customer_address
映射表中与版本相关的信息。通常,您可能会在此处指定映射有效的日期范围。
CREATE TABLE customer_address (
customer_address_id NUMBER PRIMARY KEY,
customer_id NUMBER REFERENCES customer( customer_id ),
address_id NUMBER REFERENCES address( address_id ),
valid_from DATE,
valid_to DATE
);
答案 1 :(得分:1)
正如您已经发现的那样,永远不允许不可变数据引用可变数据。答案是使引用的数据不可变。使用版本只是这样做的一个例子,但还有其他方法。
在您的订单 - 客户示例中,订单不依赖于整个客户 - 更改客户密码或创建新订单不应以任何方式影响原始订单。因此,您可以从客户中删除相关部分并使其不可变。这意味着地址是不可变的,但您仍然可以更改客户对其当前地址或地址的引用,因为客户仍然是可变的。
这可以使用关系数据库以多种方式实现。两个明显的:
您可以使地址表仅插入(不更新或删除)。这是最简单的方法,但可能会妨碍您的ORM,并将所有地址保留在数据库中,即使它们与订单无关。
保持Address表可变(允许更新和删除)。然后,每当创建新订单时,您都会创建客户当前地址的副本,并且订单引用新副本。这应该是ORM最友好的解决方案,但即使地址永远不会改变,每个订单都会获得自己的地址副本。