如何存储具有可变数量属性的java对象

时间:2012-11-20 05:10:56

标签: java database

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

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

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

5 个答案:

答案 0 :(得分: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地图很简单。上述结构中存在冗余:例如属性行中的字符“type”字段。考虑触发器进行一致性检查。

答案 1 :(得分: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();

乐意帮助

Dharam

答案 2 :(得分:0)

而不是Java,更多的是设计级问题。您必须找出定义数据库表的方法,这将有助于您找到Java对象......

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

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

现在让我们转到一个项目。一个项目属于一个类别,因此Item表格将具有category_key以具有Item n category ...的映射... Item将具有存储在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对象......

答案 3 :(得分:0)

我猜你可以用你定义表中所有对象类型的方式构建你的数据 然后使用以下方法。

你可以定义像:

这样的表格
  • OBJECT_TYPE

  • OBJECTS

  • OBJ_PROPERTY_DEF

  • OBJ_PROP_VALUES

例如。
在OBJECT_TYPE中 在这里定义所有对象类型

object_type_code(pk)obj_name

4                              car
5                              t-shirt

在OBJECTS中

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分类:

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

  • ObjectTypeData

  • 目标数据

  • ObjectPropertyDefData

  • ObjectPropertyValuesData

在ObjectData.java中

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

//setter & getters and other req props

答案 4 :(得分:0)

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

使用此设计添加数据

  1. 在此设计中用于创建数据=>您正在创建具有其属性,大小类型的某些类别(例如,鞋=> 39,40,41 ...(选项); T恤=> 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}
}