API критериев JPA 2 с @ElementCollection и т.п.

У меня есть следующие объекты

class A {
  @Id
  Integer id;

  String name;

  @ElementCollection
  @JoinTable(name = "othername", joinColumns = @JoinColumn(name = "id_a"))
  @Column(name = "name")
  List<String> othernames;
}

Я пытаюсь использовать API критериев, чтобы найти экземпляры A, используя инфиксный поиск по имени или другим именам. В основном что-то вроде этого SQL-запроса:

SELECT * FROM A
    WHERE name like '%something%'
    OR id IN (SELECT id_a FROM othername WHERE name LIKE '%something%');

Следующий код предназначен для правильной работы:

String search = "%something%";
Subquery<Integer> subquery = c.subquery(Integer.class);
Root<A> subqueryFrom = subquery.from(A.class);
subquery.select(subqueryFrom.get(A_.id));
subquery.where(builder.like(subqueryFrom.get(A_.othernames), search));

query.where(builder.or(
    builder.like(from.get(A_.name), search),
    from.get(A_.id).in(subquery)
));

Я использую здесь подзапрос, чтобы не получать повторяющиеся результаты (например, кто-то ищет "а", а имя объекта содержит "а", а другие имена также содержат "а").

Теперь этот код не работает, потому что subqueryFrom.get(A.othernames) возвращает Expression‹List‹String>>, а builder.like принимает только Expression‹String>.

На самом деле я думаю, что мой подход совершенно неверен, но в настоящее время я не могу придумать никакого другого решения.


person egore911    schedule 18.09.2012    source источник


Ответы (1)


Вам нужно использовать объединение для присоединения к отношениям коллекции. Используйте join() вместо get().

Кроме того, вам не нужно использовать подзапрос, вместо этого просто поместите соединение в корневой запрос и используйте отдельный.

См. http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Criteria#Join

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Criteria#CriteriaQuery

person James    schedule 18.09.2012