使用HQL /哪种连接类型对用户执行搜索?

时间:2014-03-18 11:42:02

标签: java sql hibernate hql

我有以下型号;

  • 我有用户和规则
  • 用户可以添加到0个,1个或更多规则
  • 规则可以包含0个,1个或更多用户

这是UserEntity类:

    class UserEntity {

    private String username;

    private List<RuleEntity> rules;

    @Column(name = "username", nullable = false, unique = true)
    public String getUsername() {
        return username;
    }

    @ManyToMany(mappedBy="users" , fetch = FetchType.LAZY)
    public List<RuleEntity> getRules() {
        return rules;
    }

    ...
}

还有RuleEntity类:

    class RuleEntity {
        private String name;

        private List<UserEntity> users;

        @Column(name = "name", nullable = false)
        public String getRuleName() {
             return ruleName;
        }

        @ManyToMany (fetch = FetchType.LAZY)
        @JoinTable(name= "RULE_USER" ,joinColumns=@JoinColumn
        (name=RuleEntity.RULE_ID, referencedColumnName="ID", insertable = true, updatable = false, nullable = false),
      inverseJoinColumns=@JoinColumn
      (name=UserEntity.USER_ID, referencedColumnName="ID", insertable = true, updatable = false, nullable = false), 
      uniqueConstraints = @UniqueConstraint(columnNames = {RuleEntity.RULE_ID, UserEntity.USER_ID}))
      public List<UserEntity> getUsers() {
         return users;
      }

      ...
  }

我正在尝试实施一项搜索,用户可以使用以下搜索:

  • 只有用户名
  • 只有一个rulename
  • 用户名和rulename

所以我正在执行2个HQL查询,一个用于返回匹配的用户,另一个用于返回匹配的规则,例如。

public SearchResults search(String maybePartialUsername, String maybePartialRuleName) {
    List<UserEntity> userEntities = hqlQuery("select distinct users from UserEntity as users inner join users.rules as rules where users.username like :maybePartialUsername and rules.ruleName like :maybePartialRuleName");

    List<RuleEntity> ruleEntities = hqlQuery("select distinct rules from RuleEntity as rules inner join rules.users as users where users.username like :maybePartialUsername and rules.ruleName like :maybePartialRuleName");

    return SearchResults(userEntities, ruleEntities);
}

当用户是至少一个规则的成员时,用于查找匹配用户名(和/或rulename)的用户的第一个HQL查询可以正常工作,但是当用户尚未添加到任何规则时,它不会返回任何结果。 / p>

更改&#39;内部联接&#39;到了一个左边的连接&#39;没有帮助。问题出在&#39; rules.ruleName之类的:maybePartialRuleName&#39;条件,如果我删除这个查询工作,但我在查询中需要这与规则表的连接成功(即用户有规则)的情况下,因此我需要按规则名称进行筛选以及用户名。

select distinct users from UserEntity as users inner join users.rules as rules where users.username like :maybePartialUsername and rules.ruleName like :maybePartialRuleName

2 个答案:

答案 0 :(得分:0)

尝试左连接

从UserEntity中选择不同的用户,因为用户将users.rules加入users.username之类的规则:maybePartialUsername和rules.ruleName like:maybePartialRuleName。

它将为您提供左侧的所有内容(本例中为userEntity)。

答案 1 :(得分:0)

这对我有用(感谢@sergiu):

以下方法创建查询的选择部分:

public List<UserEntity> search(final String maybePartialUsername, final String maybePartialRuleName)
      throws EntityException {
    final String selectUsersStatement = "select distinct users from UserEntity as users";
    final String joinUsersWithRulesClause = shouldFilterSearchBy(maybePartialRuleName) ? "inner join users.rules as rules" : null;


    return search(Joiner.on(" ").skipNulls().join(selectUsersStatement, joinUsersWithRulesClause),
        maybePartialUsername, maybePartialRuleName);
  }

然后调用一个方法(未显示)调用以下内容来构建查询的where部分:

private String buildSearchQueryFrom(final String selectStatement, final String maybePartialUsername,
      final String maybePartialRuleName) {
    final Collection<String> searchFilters = Lists.newArrayListWithCapacity(2);

    if (shouldFilterSearchBy(maybePartialUsername)) {
      searchFilters.add("users.username like :maybePartialUsername");
    }

    if (shouldFilterSearchBy(maybePartialRuleName)) {
      searchFilters.add("rules.ruleName like :maybePartialRuleName");
    }

    final String whereClauseParts = Joiner.on(" and ").skipNulls().join(searchFilters);
    return Joiner.on(" where ").skipNulls().join(selectStatement, whereClauseParts);
  }

以上方法调用的辅助方法:

protected boolean shouldFilterSearchBy(final String searchValue) {
        return !Strings.isNullOrEmpty(searchValue);
      }