【问题标题】:Filter sublists result in SQL query筛选子列表导致 SQL 查询
【发布时间】:2012-01-23 13:29:56
【问题描述】:

我有一个菜单系统,其中 MenuTabs - 顶级,它们包含 Menu 并且 Menu 包含 MenuItem s。

每个级别项目都有一个用户角色列表,应该对其可见。

我需要创建一个数据库查询来选择 MenuTabs,它只包含当前用户的可见 Menus 和可见 MenuItems。有什么办法可以用 SQL 查询来做到这一点?

我使用 JPA 和 MySql,但任何 SQL 查询都会有所帮助。

作为输入数据,我有一个当前用户的角色列表,我需要为他/她构建正确的菜单系统。所以用户只会看到允许的 MenuTabs / Menus / MenuItems

类:

class MenuTab { 
   List<Menu> menu; 
   List<Role> userRoles;
}

class Menu {
   List<MenuItem> menuItems; 
   List<Role> userRoles;
}

class MenuItem {
   List<Role> userRoles;
}

class User {
   List<Role> userRoles;
}

表格:

menutab            menutab_menu              menutab_role
  id                  menutabId                 menutabId
                      menuId                    roleId


menu               menu_menuitem             menu_role
  id                  menuId                    menuId
                      menuitemId                roleId


menuitem           menuitem_role
  id                  menuitemId
                      roleId


role
   id

user                user_role
   id                 userId
                      roleId

【问题讨论】:

  • 如果您想要 SQL 答案,表结构会比类结构更有帮助(尽管我认为它们会相似)。
  • 表结构是相同的,我们使用 JPA (Hibernate),它从 Java 代码创建表。如果需要,我可以提供结构。谢谢你的评论
  • 我认为他们是必要的。
  • 很高兴看到您到目前为止所做的尝试。您可能只需要一些正确方向的指针。 (此外,认为您只是在帮助某人而不是为他们做他们的工作总是更好。)还有一个不同点的问题。 MenuTabs、Menus 和 MenuItems 是否应该匹配所有输入列表中提供的角色,还是至少匹配一个就足够了?
  • 我不确定是否可以使用查询。我试图做这样的事情:SELECT tab FROM MenuTab tab WHERE EXISTS (SELECT 1 FROM tab.userRoles role WHERE role MEMBER OF :rolesList) 这是 JPA 查询,我没有尝试编写 SQL 查询

标签: mysql sql jpa filter sublist


【解决方案1】:

如果您使用的是 Hibernate,则不必处理 sql 我不熟悉 Hibernate,但在 NHibernate 中你可以像这样使用 HQL:

var _query = DetachedCriteria.For<MenuTab>()
                                .Add(Restrictions.In("userRoles", listOfRoles)
                                .Add(Restrictions.In("MenuItem.userRoles", listOfRoles);

【讨论】:

    【解决方案2】:

    在 SQL 中,我可能会做这样的事情:

    SELECT
      ...
    FROM menutab_menu tm
      INNER JOIN menu_menuitem mi ON tm.menuId     = mi.menuId
      INNER JOIN menutab t        ON tm.menutabId  = t.Id
      INNER JOIN menu m           ON tm.menuId     = m.Id
      INNER JOIN menuitem i       ON mi.menuitemId = i.Id
    WHERE
      t.Id IN (
        SELECT tr.menutabId
        FROM menutab_role tr
          INNER JOIN user_role ur ON tr.roleId = ur.roleId
        WHERE ur.userId = @userId
      )
      AND m.Id IN (
        SELECT mr.menutabId
        FROM menu_role mr
          INNER JOIN user_role ur ON mr.roleId = ur.roleId
        WHERE ur.userId = @userId
      )
      AND i.Id IN (
        SELECT ir.menutabId
        FROM menuitem_role ir
          INNER JOIN user_role ur ON ir.roleId = ur.roleId
        WHERE ur.userId = @userId
      )
    

    假设@userId是当前用户ID,作为参数传递给查询。

    【讨论】:

    • 谢谢,我会尝试翻译成JPA并发布结果
    • 感谢 Andriy,您的脚本在我的数据库中工作,但我无法使用 JPA 来完成。我正在尝试这个SELECT DISTINCT tab FROM MenuTab tab JOIN tab.userRoles tr JOIN tab.menus menu JOIN menu.items item JOIN menu.userRoles mr JOIN item.userRoles ir WHERE tr IN (:rolesList) AND mr IN (:rolesList) AND ir IN (:rolesList),但它什么也没返回。我也尝试过不使用项目,只获取 menuTabs 和菜单,但它返回了包含所有菜单的可见选项卡。我决定使用 Java 进行过滤。非常感谢您的帮助!
    • @Svetlana:我的荣幸!据我所知,您不能像这样对IN() 列表进行参数化。查看this question,并查看其Linked 部分,其中包含对许多类似问题的引用。也许其中一些对你有帮助。
    • IN (:rolesList) 在其他地方为我们工作,我用它来获取菜单选项卡,所以我认为这不是失败的原因。感谢您提供的链接,我将查看它们
    猜你喜欢
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-04
    • 1970-01-01
    • 2021-12-08
    相关资源
    最近更新 更多