如何用XML或其他简单文件格式表示多对多关系?

时间:2010-06-17 22:08:23

标签: java xml android database database-design

我有一个列表管理应用程序,可将其数据存储在多对多关系数据库中。

即。注释可以包含任意数量的列表,列表可以包含任意数量的注释。

我也可以将此数据导出到XML文件,然后将其导入我的应用程序的另一个实例,以便在用户之间共享列表。但是,这是基于遗留系统,其中要注释的列表关系是一对多(XML的理想选择)。

现在,多个列表中的注释在数据库中基本上被分成两个相同的行,并且它们之间的所有关系都将丢失。

问题:如何以简单的标准文件格式表示这种多对多关系? (最好使用XML来保持向后兼容性)

5 个答案:

答案 0 :(得分:6)

我认为您的XML格式必须使用某种“引用”。如果您希望列表到注释的关系可见,那么类似下面的内容可能是合适的:

<notes>
    <note id="Note1"> ... </note>
    <note id="Note2"> ... </note>
    ...
</notes>

<lists>
    <list id="List1">
        <note_refs>
            <note_ref id="Note1"/>
            <note_ref id="Note4"/>
        </note_refs>
    </list>
    ...
</lists>

另一方面,如果您希望轻松查看与给定音符关联的列表,则可以在我的示例中简单地反转列表和音符的角色。

或者,您可以更对称地表示多对多关系作为数学关系:定义所有注释,定义所有列表,然后定义由[列表引用,注释引用]对组成的映射。

答案 1 :(得分:3)

在数据库中,用于表示多对多关系的工具是关联表。表中的每一行代表两个对象之间的关联。因此,如果ID为1的注释出现在ID为1,2和3的列表中,则关联表中将有三行:

 ID  NoteID  ListID
 --  ------  ------
  1       1       1
  2       1       2
  3       1       3

您可以通过以下查询获取备注及其所有相关列表:

SELECT [columns] FROM Association
   JOIN Notes ON Note.ID = Association.NoteID
   JOIN Lists ON List.ID = Association.ListID
WHERE Association.NoteID = @NoteID

列表的所有注释:

SELECT [columns] FROM Association
   JOIN Notes ON Note.ID = Association.NoteID
   JOIN Lists ON List.ID = Association.ListID
WHERE Association.ListID = @ListID

这就是你用XML表示它的方式:

<Lists>
  <List ID='1'>...</List>
  <List ID='2'>...</List>
  <List ID='3'>...</List>
  ...
<Lists>  
<Notes>
  <Note ID='1'>...</Note>
</Notes>
<Associations>
   <Association ID='1' NoteID='1' ListID='1'/>
   <Association ID='2' NoteID='1' ListID='2'/>
   <Association ID='3' NoteID='1' ListID='3'/>
</Associations>

在XSLT中,您可以像这样访问此关联:

<xsl:template match="List" mode="AssociatedNotes">
   <xsl:variable name="Associations" select="/*/Associations/Association[@ListID=current()/@ID]"/>
   <xsl:apply-templates select="/*/Notes[@ID=$Associations/@NoteID]"/>
</xsl:template>

<xsl:template match="Note" mode="AssociatedLists">
   <xsl:variable name="Associations"  select="/*/Associations/Association[@NoteID=current()/@ID]"/>
   <xsl:apply-templates select="/*/Lists[@ID=$Associations/@ListID]"/>
</xsl:template>

(注意使用mode属性来防止这些模板相互调用,直到出现堆栈溢出。)

答案 2 :(得分:0)

我能想到的唯一方法是在XML或任何其他层次结构中真正表示多对多关系,就是使用许多一对多关系。

这是一个简单的例子:

<list name="listA">
    <notes name="noteA" />
    <notes name="noteB" />
    <notes name="noteC" />
</list>
<list name="listB">
    <notes name="noteB" />
    <notes name="noteC" />
    <notes name="noteD" />
</list>

换句话说,每个列表都将其注释作为子节点。

许多笔记子节点将在XML文件中重复。从XML文件填充数据库的过程必须考虑重复的注释子节点。

另一种选择是为每个音符选择一个列表。注释将只是其中一个列表的子节点。优点是没有任何重复的注释。缺点是XML文件并不代表正确列出关系的注释,这可能重要也可能不重要。

答案 3 :(得分:0)

我的第一步将是简单的:

<notes>
  <note>
    <title>Groceries to get</title>
    <list>shopping</list>
    <list>urgent</list>
    <body>eggs, cheese, milk</body>
  </note>
</notes>

这符合您的需求吗?

答案 4 :(得分:0)

就这样做:

<notes>
    <note id="1">
        <name>George</name>
        <text>1984</text>
        <notesLinks>
            <listId id="1"/>
        </notesLinks>
    </note>
    <note id="2">
        <name>George</name>
        <text>animal farm</text>
        <notesLinks></notesLinks>
    </note>
</notes>
<lists>
    <list id="1">
        <notesLinks>
            <noteId id="1"/>
            <noteId id="2"/>
        </notesLinks>
        <name>some info</name>
    </list>
</lists>