PostgreSQL - 管理用户的联系人 - 单向还是双向关系更好?



我正在研究如何使用Vaadin+JPA+EclipseLink+PostreSQL来开发用于共享图片的web应用程序,以及这种组合适合此目的的程度。我正在为管理用户联系人的决定而挣扎。在解释我的表的结构之后,我将对此进行更详细的讨论:

Users表

users表由以下列组成:

  • 用户ID-注册时自动生成(唯一)
  • 用户名-使用者的名称;注册时定义(唯一)
  • -用户的密码;注册时定义的
  • <
  • 上传/strong>-用户上传的所有图片id。我不想在这里详述,因为这与我的问题无关。只需说明此列与另一个名为Images的表一起使用即可。用于管理当前用户的图库

联系人表

这个表纯粹是为了存储用户之间的关系信息(我的一个同事决定这样做,坦率地说,我不喜欢,但它已经这样做了…)。它只有两列:

  • 用户ID-拥有联系人的用户ID(见下文)
  • 联系人
  • -存储user ID用户的所有用户ID已允许查看他的图片库。

    注意:这是而不是双向关系。这意味着当用户X将用户Y添加到他的联系人中时,用户X授予对他自己的的访问权限。但是,这并不能使用户X看到用户Y的图库。只有当用户Y也将用户X添加到他的联系人中时,才会发生这种情况。形象可以是公共的,也可以是私人的。所有用户都可以查看公共图像,但是私有图像只能由拥有这些图像的用户以及所有者通过将其添加到其联系人中授予访问权限的所有其他用户查看。"隐私"在这里可能不是最好的术语,所以你可能会把它看作是"允许朋友查看"之类的东西。

每当我删除一个用户时,我必须做以下操作:

  1. 删除用户上传的所有图像文件-Images中的图像表只有一个上传器。查看状态:简单地删除文件并从Images中删除其条目是完全安全的因为每个图像都绑定到它的上传者而不是其他人(受影响):Images表,存储)
  2. 删除用户的文件夹-遗憾的是,Java的工作方式,你必须首先确保一个文件夹是空的,然后再删除它(影响:存储)
  3. 从所有用户的联系人列表中删除用户-THIS HERE是我遇到的主要困境(影响:Users表)
  4. 删除用户本身(受影响:Users)表)

因为到目前为止我写的查询,这个顺序基本上是应该的。考虑到我的表之间的关系,我发现这是最优的。

正如我在3中提到的我对如何以尽可能少的努力(编码和性能方面)做到这一点非常困惑。我正在寻找两个解决方案:

  • 单向关系-不要更改Users然后遍历其中的所有用户然后遍历每个用户的联系人查找我要删除的当前用户的用户ID

  • 双向关系Users中添加一个新列叫做addedBy存储已将我要删除的当前用户添加到其联系人的用户的所有用户id。每次用户X将另一个用户添加到他的联系人时,该用户将用户X"添加"到他的adddedby列表但不包括联系人.

我在单向关系中看到的问题就是我必须遍历所有用户,然后检查每个用户的联系人,看看它是否包含我想要删除的用户ID。

我在双向关系中看到的问题是随新列一起添加的开销。不过,这里最大的好处是,我可以跳过查看所有用户的联系人(当然,最坏的情况是用户已被添加到所有用户的联系人中,这是不太可能发生的;))并且只对adddedby中的用户执行此操作列表。

我远非数据库专家,正如您可能从上面所写的那样,可能有更好的做事方式。但是,我只对上面提到的两个版本感兴趣,并且对DB的更改尽可能少。我也不知道哪个查询更容易写。我已经设法完成了删除过程中的所有其他步骤(1、2和4),但第三步是一个艰难的步骤。

你知道哪个更好吗?用户的数量并不重要,因为这纯粹是为了研究,但是在users中有几百/几千个条目。

我认为你的同事的方法是对的,但没有全力以赴。

"Contacts table",这个表看起来像一个多对多关系表。

但是问题正如你所描述的:

Contacts—存储具有user ID的用户给出的所有用户ID允许查看他的图片库。

在一个真正的多对多关系表中,你应该有两列

  • 'user_id',你已经有了什么

  • 'contact_user_id'(命名显然可以不同),但主要的一点是,每个联系人在这个表中只有一行。

所以当你删除一个用户并想从所有联系人列表中删除这个用户时你可以简单地说:

delete from Contacts where contact_user_id = :userIdOfUserToBeDeleted

正如@Predrag Maric所描述的那样,这将使您的数据库数据更加健康,不仅在user_id上,而且在链接的contact_user_id上。

如果您使用JPA或类似的,这也会有所帮助,例如,您可以使用JPA有一个删除策略,您可以将其设置为级联来删除那些引用。但这只在完全规范化的表中支持。

最新更新