【问题标题】:Optimize hibernate criteria query to become more dynamic优化休眠条件查询变得更加动态
【发布时间】:2013-01-22 02:23:40
【问题描述】:

我正在使用带有大量条件的休眠条件查询。查询是否包含应用程序状态和角色的采购申请表。所以为了简单起见,所有表格都以状态 1 或草稿开始。保存表单后,当前用户成为创建者。创建者可以将其他用户分配给表单,例如授权人或联系人。这些是我认为的动态角色。所以我表格的前三个状态如下,

State 1 "Draft" role Creator
State 2 "Authorizer" role Authorizer
State 3 "Contact" role Contact

一旦您离开状态 3 并进入状态 4,应用程序现在将进入管理员角色。在表格最终获得批准和关闭之前,最多可能有 15 个州。直到最后四个状态,Creator、Authorizer 和 Contact 将继续具有访问权限。最后四个州,他们将无法访问。

除非管理员是创建者、授权者或联系人,否则用户将无法访问前三个状态,但将继续访问最后一个状态,包括非管理员没有的其余四个状态也没有访问权限。

我当前的查询如下所示,但是作为管理员,我希望不必手动硬编码每个 applicationState 以添加到查询中并添加所有这些,但排除管理员不在的状态在动态角色创建者、授权者或联系人中。

此查询有效,但非常混乱。

Disjunction programRoles = Restrictions.disjunction();
            programRoles.add(Restrictions.eq(Role.ROLE_CREATOR, user));
            programRoles.add(Restrictions.eq(Role.ROLE_AUTHORIZER, user));
            programRoles.add(Restrictions.eq(Role.ROLE_CONTACT, user));

            if(roleManagerService.isAdmin()) {
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.ARCHIVED.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.ASSESSOR_REVIEW.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.ASSIGNOR_REVIEW.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.AUDITOR_REVIEW.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.BURIED.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.DEAD.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.FINAL.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.FINAL_MAJOR_APPROVAL.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.FINAL_MINOR_APPROVAL.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.IFAS_LOAD.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.PO_COLLECTION.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.PO_DISTRIBUTION.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.PO_EVALUATION.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.PURGE.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.SECONDARY_MAJOR_REVIEW.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.SECONDARY_MINOR_REVIEW.name()));
                programRoles.add(Restrictions.eq("currentState.prStateCode", ApplicationStateEnum.SECONDARY_OVERHEAD_REVIEW.name()));
            }

        Criteria results = this.session.createCriteria(PurchaseRequest.class)
                .createAlias("currentState", "currentState")
                .add(programRoles);

                if(!roleManagerService.isAdmin()) {
                    results.add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.DEAD.name()))
                            .add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.ARCHIVED.name()))
                            .add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.FINAL.name()))
                            .add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.BURIED.name()));
                }

我想知道是否有人可以为我指明一个清理这个问题的方向,让它变得更有活力。

【问题讨论】:

  • 会询问 roleManagerService 的 Collection CandidateApplicationStates() 和 Collection excludeApplicationStates() 工作吗?然后你只需做一个 Restrictions.in 或循环来添加 ne。您可能会从尝试将这种逻辑放入一个知道它们是否是管理员并且可以做出决定的类中获得一些好处。尝试限制该布尔值的范围。
  • @roby,我可以,但是所有这些状态都保存在数据库中,并且可以动态添加/减去,所以我希望不必对其进行硬编码。我几乎在想必须有一种方法可以为管理员返回所有结果,除了前三个状态中不包含当前用户的结果。我今天似乎无法思考。

标签: java hibernate


【解决方案1】:

我还没有真正尝试过,但可能只是添加了不允许管理员用户查看的限制。 比如:

Disjunction programRoles = Restrictions.disjunction();
programRoles.add(Restrictions.eq(Role.ROLE_CREATOR, user));
programRoles.add(Restrictions.eq(Role.ROLE_AUTHORIZER, user));
programRoles.add(Restrictions.eq(Role.ROLE_CONTACT, user));

// change starts here
if(roleManagerService.isAdmin()) {
    Conjunction notHiddenStateForAdmin = Restrictions.conjunction();
    notHiddenStateForAdmin.add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.FIRST_STATE.name()));
    notHiddenStateForAdmin.add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.SECOND_STATE.name()));
    notHiddenStateForAdmin.add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.THIRD_STATE.name()));
    programRoles.add(notHiddenStateForAdmin);
}

// rest unchanged
Criteria results = this.session.createCriteria(PurchaseRequest.class)
       .createAlias("currentState", "currentState")
       .add(programRoles);

if(!roleManagerService.isAdmin()) {
     results.add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.DEAD.name()))
            .add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.ARCHIVED.name()))
            .add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.FINAL.name()))
            .add(Restrictions.ne("currentState.prStateCode", ApplicationStateEnum.BURIED.name()));
}

【讨论】:

  • Klein-Robbenha 您的解决方案的唯一问题是,一旦我们超过第三个状态并进入第四个状态,它只会为我提供包含我作为创建者、授权者或联系人的结果.一旦处于第四种状态,我将需要与所有用户一起查看它,例如,如果 John doe 是创建者、授权人和联系人,那么如果表单处于这些状态中的任何一种,我就不应该看到他,但是一旦它使在这些州之外,我应该以管理员的身份看到结果。只有当我被分配到其中一个状态时,我才能看到这些状态的任何结果。
  • 好的,回到绘图板...嗯,我编辑了我原来的答案,而不是创建一个新的答案,所以它现在只过滤来自管理员的“禁止”初始状态(不确定是什么名称是 ,所以它们是 FIRST_STATE ... 等等)。希望这会更好。 (顺便说一句,我应该创建一个新答案而不是编辑编辑答案吗?我不确定什么是正确的行为,因为我在这里很新)
  • 谢谢,到目前为止它似乎工作正常。我今天下午通过我们的测试人员运行它。提供没有错误,我会投票给你最好的答案。感谢所有帮助。
猜你喜欢
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 2015-08-14
  • 2011-04-13
相关资源
最近更新 更多