我看过How to store data with dynamic number of attributes in a database,但它并没有完全回答我的问题。我实现的系统相当大,所以我会坚持我关注的对象:项目和类别。 Item具有可变数量的属性,具体取决于它所属的类别。例如,属于“T恤”类别的项目将具有大小属性,而属于“汽车”类别的项目将具有模型属性。有人以管理员身份登录系统可以创建具有全新属性的新类别。在我的Java代码和数据库中构建这个结构的最佳方法是什么?
如果类别不是动态创建的,我会使用继承,这样我就会得到一个填充了特定属性的TShirtItem对象。但由于它是动态的,我很困惑。我看到了一个类似的问题建议使用Map数据结构,但我不确定它是如何工作的......
我在顶部提到的问题将在数据库端建议我将有一个Category表,Attributes表和关系表将哪些属性与哪个类别相关联。这是有道理的。但是在考虑Item对象时我又被绊倒了。我可以在Item表中存储唯一的Category_ID,但是我在哪里存储每个Item的属性?
答案 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实体,该实体存储具有颜色,大小的确切项目-用条形码标识-但为简单起见而省略)。这种设计将有助于而不是硬编码属性的某些部分,这对于项目的分类很重要。
在此设计中用于创建数据=>您正在创建具有其属性,大小类型的某些类别(例如,鞋=> 39,40,41 ...(选项); T恤=> S,M, L ...,Iphone 7,8,X ...)=>此类别中的特定文章-Iphone(通过这种方式在您的电子商务系统上存在Iphone)
您向仓库或库存中添加特定的商品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}
}