3

我看过How to store data with dynamic number of attributes in a database,但它并没有完全回答我的问题。我正在实现的系统相当大,所以我会坚持我关心的对象:项目和类别。一个项目具有可变数量的属性,具体取决于它所属的类别。例如,属于“T-shirt”类别的项目将具有大小属性​​,而属于“汽车”类别的项目将具有模型属性。以管理员身份登录系统的人可以创建具有全新属性的新类别。在我的 Java 代码和数据库中构建它以使其工作的最佳方法是什么?

如果类别不是动态创建的,我会使用继承,这样我就有一个填充了特定属性的 TShirtItem 对象。但由于它是动态的,我很困惑。我看到了一个类似的问题,建议使用 Map 数据结构,但我不确定它是如何工作的......

我在顶部提到的问题会在数据库端建议我将有一个类别表、属性表和关系表,这些表将哪些属性与哪些类别相关联。这是有道理的。但是在考虑 Item 对象时,我又被绊倒了。我可以将唯一的 Category_ID 存储在 Item 表中,但是我将在哪里存储每个 Item 的属性?

4

5 回答 5

3

如果您受限于使用 SQL 数据库,并且需要对属性进行有效的类型感知(不仅仅是字符串)查询(例如列出所有尺寸在 4 到 8 之间的衬衫类别的项目),那么数据库的结构是困难的部分。Java 将随之而来。如果我理解正确,您将需要这样的东西:

categories:
  id : integer (pk)
  name : varchar

attributes:
  id : integer (pk)
  of_category : integer (fk -> categories.id)
  name : varchar
  type : char(1) // 'N' for number, 'S' for string, etc.

items:
  id : integer (pk)
  of_category : integer (fk -> categories.id)

number_values:
  value : number
  of_item : integer (pk, fk -> items.id)
  of_attribute : integer (pk, fk -> attributes.id)

string_values:
  value : varchar
  of_item : integer (pk, fk -> items.id)
  of_attribute : integer (pk, fk -> attributes.id)

... additional table for each attribute type

现在对于示例查询:

select * from categories c, items i, attributes a, number_values v
where c.name = 'shirt' and
      a.of_category = c.id and
      a.name = 'size' and
      a.id = v.of_attribute and
      i.id = v.of_item and
      v.value between 4 and 8

毛茸茸的多重连接是为运行时定义的属性付出的代价。

一旦您拥有正确的表格,将它们建模为 Java 地图就很简单了。上述结构中存在冗余:例如属性行中的字符“类型”字段。考虑使用触发器进行一致性检查。

于 2012-11-20T05:56:22.437 回答
2

这是一个简单的java方法来做到这一点。在设计大型系统时,我总是建议着眼于更大的图景。这里的问题是动态改变属性。这并不容易,但是是的,这很有趣。

您的项目类的结构必须如下所示:

class Item{
   private String itemName; // I assume all items will have a name.
   private Map<ItemAttibuteName , Object> attributeMap ; // this will be a dynamic map.

   public Map<ItemAttibuteName, Object> getAttributeMap(){//getter for attribute map
       if( null == attributeMap)
          return new HashMap<String, Object>(); 
       return attributeMap ;

   }
   // you can synchronize this if needed
   public void setAttribute(ItemAttibuteName name, Object value){ 
       attributeMap.put(name, value);
   }

   public Object getAttribute(ItemAttibuteName name){ 
       return attributeMap.get(name);
   }
}

public enum ItemAttibuteName{
    SIZE,
    COLOUR        
}

这种方法适合您的需求,此外,您可以使用工厂模式根据类别实例化项目并使其成为优雅的代码。

如果您仍有疑问,请返回。

编辑: 现在将有一种复杂的方法在编程时获取代码中元素的所有属性,因为您没有属性的 getter 或 setter。好吧,如果您可以在 Item 类中维护添加到 Item 的一组属性,或者您可以查询 item 类的 attributeMap 属性的 keySet,则该方法将有所帮助。

private Set<ItemAttibuteName> attributes;

或者

attributeMap.keySet();

很高兴能帮助你

达拉姆

于 2012-11-20T05:26:03.827 回答
0

而不是Java,它更多的是设计级别的问题。您必须弄清楚定义数据库表的方法,这将帮助您找到 Java 对象......

让我们从类别开始......一个类别可能包含很多项目,一个项目将只属于一个类别(虽然我在实际场景中这不是一个正确的假设)。

所以在 DATABASE 中有一个名为 Category 的表。如果你想根据类别定义属性,那么有另一个名为 Category_attribute 的表,它将保存属性的默认值。

现在让我们移动到一个项目。一个项目属于一个类别,因此项目表将具有 category_key 以具有项目 n 类别的映射...项目将具有其存储在 ITEM_Attribute 表中的属性...

DB对象的简单形式必须有点如下所述

Category
C_Id
Name


Category_Attribute
CA_ID
Name
Default_value
Category_Id(FK)


Item
I_ID
Name
C_ID(FK)


Item_attribute
IA_ID
Ca_ID(FK from category_attribute table)
I_ID(FK from item table)
Value

因此,每当您创建一个类别时,您都会要求用户为该类别定义相关属性。

在创建项目时,您将其映射到类别...并且与类别关联的属性应该使用默认值复制并映射到项目...

因此,您将能够轻松地创建 Java 对象...

于 2012-11-20T06:16:09.643 回答
0

我想您可以通过在表中定义所有对象类型然后使用以下方法来构建您的数据。

你可以定义如下表:

  • OBJECT_TYPE

  • 对象

  • OBJ_PROPERTY_DEF

  • OBJ_PROP_VALUES

例如。
在 OBJECT_TYPE 此处定义所有对象类型

object_type_code(pk) obj_name

4                              car
5                              t-shirt

在对象

obj_code(pk) object_type_code(fk) obj_name


1           4       BMW  
2           4       Maruti  
3           4       Honda  

4           5       levis  
5           5       polo  
6           5       reebock  

在 OBJ_PROPERTY_DEF

定义与此表中的对象对应的所有属性。

注意:使用常量文件来定义属性类型会避免另一个表。希望当您更早地了解数据类型时。

obj_prop_code(pk) obj_code(fk) property_type property_name

------------- -------- ------------- -------------

12          6       8 (Integer)     size  
13          6       9 (String)      color  
14          6       10 (float)      weight  
15          6       11 (Boolean)        is_coloured  
16          6       9 (String)      comments  

17          3       9 (String)      model  
18          3       8 (Integer)     version  
19          3       9 (String)      color  
20          3       9 (String)      comments  

在 OBJ_PROP_VALUES U 中可以插入上述指定属性的值

obj_prop_val_code(pk) obj_prop_code(fk) obj_prop_value(VARCHAR) prop_value_sufix

----- ------------- -------------- ------ ------------

101             12          30              -  
102             13          green           -  
103             14          126            gms  
104             15          0               -
105             16          looks cool      -  

106             17          c532            -  
107             18          3.22            -  
108             19          black           -  
109             20          awesome car     -   

Reg Java 分类:

定义具有相应属性的所有类。例如:

  • 对象类型数据

  • 对象数据

  • 对象属性定义数据

  • 对象属性值数据

在 ObjectData.java 中

private ObjectTypeData          objType;//specifies the type
private List<ObjectPropertyValueData>   listProps; //will have all property values

//setter & getters and other req props

于 2012-11-20T06:30:50.493 回答
0

我认为有些属性是主要的(尺寸,颜色......),有些是次要的(材料,重量......)。我将为此描述简化的JDL模式(当然存在另一个 Stock 实体,它存储具有颜色、大小的确切项目 - 用条形码标识 - 但为简单起见而省略)。这种设计将有所帮助,而不是硬编码对物品分类很重要的属性的某些部分。

使用此设计添加数据

  1. 在此设计中创建数据 => 您正在使用它的属性、尺寸类型创建一些类别(例如鞋子 => 39,40,41...(选项);Tshirt => S,M,L..., Iphone 7,8,X...) => 在此类别中的特定文章 - Iphone(在您的电子商务系统上以这种方式存在 Iphone)

  2. 您将特定的 Iphone X(尺寸) - 颜色黑色添加到您的仓库或库存中,并带有额外的类别相关属性 => 材料、重量 .... 和系统为您生成的条形码。通过这种方式,您可以轻松地指定 Iphone 的大小和颜色(无需额外的 sql - 使用纯 ORM)(即使有额外的属性)


enum CategoryTarget{
    F, M, K
}

entity Category{
    name String,
    imageUrl String,
    showHomepage Boolean,
    target CategoryTarget,
    accOrder Integer,
    isLastNode Boolean
}

entity Article{
    status Integer,
    name String,
    code String,
    rating Double,
    imageUrl String,
    isPopular Boolean
}

relationship ManyToOne{
    Category{parent} to Category,
    Article{category} to Category{article},
    Category{sizeType} to SizeType
}

relationship ManyToMany{
    Category{attribute} to Attribute{category}
}

entity Attribute{
    name String
}

entity AttributeOption{
    name String
}

relationship OneToMany{
    Attribute{attributeOption} to AttributeOption{attribute}
}

entity SizeType{
    name String
}

entity ArticleSize{
    name String,
    accOrder Integer
}

relationship OneToMany{
    SizeType{articleSize} to ArticleSize{sizeType}
}

relationship ManyToMany{
    Article{attributeOption} to AttributeOption{article}
}

于 2019-06-13T07:28:04.447 回答