更新聚合时重新创建数据库耦合行是常见做法吗?

问题描述 投票:0回答:1

想象一下我们有一个包含产品的 CRUD 系统。每个

Product
可以有代表产品属性的
Attributes
,如尺寸、颜色、重量等。这是一个典型的EAV数据库案例(实体、属性、值)。 简单来说,数据库方案如下:

产品

id | name | description

属性

id | name | data_type

eav_关系

id | entity_id | attribute_id 

小数值

id | eav_relation_id | value (column type decimal)

varchar_values

id | eav_relation_id | value (column type varchar)

..._值

Similar as the other values tables but for different data types, like bool_values, file_values, etc.

enter image description here

提供上下文:

eav_relations 保持产品及其属性之间的联系。 ..._values 表包含一个 eav_relation_id,它指向 eav_relations 中的一行。一个属性可以有多个值(例如“标签/关键字”的集合或多个文件)。

加载产品时,我们可以从数据库结构构建整个产品聚合,这是显而易见的。 但是当创建/更新产品时,客户端发送产品表示如下:

{
    "name": "The product name",
    "description": "Example product.",
    "attribute_groups": [
        {
            "group_name": "Product propeties",
            "attributes": [
                {
                    "attribute_id": 3,
                    "values": [433.9]
                },
                {
                    "attribute_id": 9,
                    "values": ["wifi", "LAN"]
                }
            ]
        },
        {
            "name": "Shipping",
            "attributes": [
                {
                    "attribute_id": 19,
                    "values": [12.5]
                },
                {
                    "attribute_id": 24,
                    "values": ["ECommercePost Ltd."]
                }
            ]
        }
    ]
}

创建产品时,在数据库中创建关系数据相对简单。 但更新时就比较复杂了。属性可以被添加或删除,属性的值可以被更改/添加/删除。最简单的方法是删除并重新创建 eav_relations 中与产品对应的所有行,并删除并重新创建 ..._values 表中的所有行。重新创建时,自动增量将生成新的 id。缺点是行 id 在产品的每次更新时都会发生变化,而只要 id<->id 耦合保持正确,这在技术上并不是很重要。

否则,您必须在更新请求的 JSON 中提供所有 eav_relations..._values 的行 ID。然后检查具有这些 id 的行是否存在,如果存在,则更新它们。当存在“null”id 时,表示该属性是新添加到产品中的,如果属性值具有“null”id,则表示该值是新的。此外,在处理请求之前,您必须加载整个产品聚合,并检查数据库中是否有行的 id 在请求 JSON 中出现“不再”。在这种情况下,应删除该行(因为从产品中删除了属性或属性值)。 更新请求的 JSON 将变为如下所示:

{ "name": "The product name", "description": "Example product.", "attribute_groups": [ { "group_name": "Product propeties", "attributes": [ { "eav_relation_id": 2, // Existing eav_relation id provided in request, the attribute is preserved. "attribute_id": 3, // attribute_id is the same. If the attribute id would have been changed, the column will be updated in eav_relations. It's like the attribute would be swapped with some other... "values": [ { "id": 291, // Existing decimal_values row id is provided, the row will be kept but the value column will be updated. "value": 123.9 } ] }, { "eav_relation_id": null, // A null id means the attribute is added. "attribute_id": 98, "values": [ { "id": null, "value": "orange" }, { "id": null, "value": "blue" } ] } // There was an attribute with id 9, (and values "wifi", "LAN") but this is no more present in the // request. It's considered as dropped and thus the corresponding rows will be deleted. ] }, // The group "Shipping" is no more present in the request, and so the eav_relation_ids do not occur in the request. // All eav_relations and ..._values rows for the product, that have a row id that is no more present in the request // will be deleted. ] }

很明显,这带来了很大的复杂性,甚至令人难以理解。
我的想法是始终将产品行保留在 
products

表中,因此产品 ID 永远不会改变,因为这是实际上可以在 URL 中使用的重要标识符。其他“更深层次”的 id 实际上只是为了在内部保持数据之间的关系。 我的问题是,通常的做法是删除并重新创建整个聚合,还是我们应该更新并“回收”数据库行以避免自动增量并保留内部用于连接行的原始行 ID。

php mysql database-design crud entity-attribute-value
1个回答
0
投票

相反,您可以添加一个可以在

eav_relations

轻松复制产品和属性的唯一标识符,并且可以为

attributes
decimal_values
varchar_values
创建临时表,在其中插入事物的当前状态以及一个临时的
eav_relations
,您还将在其中拥有这个新的唯一标识符(如果本质上是同一产品的相同属性,则它应该与实际表中的对应值匹配)。因此,您可以从
eav_relations
中删除并级联所有在临时对应项中不匹配的记录,执行更新和插入。
此外,如果您已有十进制或 varchar 值,并且存储属性的值表已更改,那么您也需要转换和迁移属性值。

© www.soinside.com 2019 - 2024. All rights reserved.