Выполнить поиск, используя HQL / какой тип присоединения к пользователю?

1

У меня есть следующая модель;

  • У меня есть пользователи и правила
  • пользователь может быть добавлен к 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;
      }

      ...
  }

Я пытаюсь выполнить поиск, посредством которого пользователь может выполнить поиск, используя:

  • только имя пользователя
  • только имя
  • имя пользователя и имя

Поэтому я выполняю 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);
}

Первый запрос HQL для поиска пользователей, соответствующих имени пользователя (и/или имени), отлично работает, когда пользователь является членом хотя бы одного правила, но не возвращает никаких результатов, когда пользователь не был добавлен ни к каким правилам.

Изменение "внутреннего соединения" на "левое соединение" не помогает. Проблема заключается в условии "rules.ruleName like: maybePartialRuleName", если я удалю этот запрос, но мне нужно это в запросе в случаях, когда успешное соединение с таблицами правил (т.е. у пользователя есть правила), и поэтому мне нужно фильтровать по имени правила, а также по имени пользователя.

select distinct users from UserEntity as users inner join users.rules as rules where users.username like :maybePartialUsername and rules.ruleName like :maybePartialRuleName
Теги:
hibernate
hql

2 ответа

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);
  }

Затем он вызывает метод (не показан), который вызывает следующее для построения тех частей запроса:

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);
      }
0

Попробуйте присоединиться

выберите отдельных пользователей из UserEntity, так как пользователи оставили join users.rules как правила, где users.username like: maybePartialUsername и rules.ruleName like: maybePartialRuleName.

Это даст вам все, что в левой части (userEntity в этом случае).

  • 0
    спасибо, хотя левое соединение также не работает, оно возвращает нулевые результаты, как и при внутреннем соединении, проблема в том, что при левом / внутреннем соединении этот раздел sql 'rules.ruleName вроде: MaybePartialRuleName' вызывает возврат результата ноль результатов.
  • 0
    Есть ли запись, которая соответствует обоим условиям?
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню