Запрос JPQL «НЕ ЧЛЕН», используя API критериев - PullRequest
1 голос
/ 17 мая 2011

Учитывая следующие аннотированные классы сущностей JPA:

@Entity
@Table("foo")
public class Foo {
    @Id private int id;
    @Column(name="name") private String name;
    @ManyToMany
    @JoinTable(name = "foo_tags",
           joinColumns = {@JoinColumn(name = "foo")},
           inverseJoinColumns = {@JoinColumn(name = "tag")})
    private Collection<Tag> tags;
    ...
}

@Entity
@Table(name = "tag")
public class Tag {
    @Id private String tag;
    ...
}

Я пытаюсь сформулировать запрос, чтобы получить все экземпляры Foo, в которых отсутствует данный тег.Следующий JPQL-запрос делает трюк

SELECT f FROM Foo f WHERE :tag NOT MEMBER OF f.tags

Однако у меня возникли проблемы с переводом этого запроса в критерии.Перевод кажется очевидным (для меня):

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Foo> query = cb.createQuery(Foo.class);
Root<Foo> from = query.from(Foo.class);
query.where(cb.isNotMember(cb.parameter(Tag.class, "tag"), from.get(Foo_.tags)));
TypedQuery<Foo> tq = em.createQuery(query);
return tq.setParameter("tag", sometag).getResultList();

Хотя сгенерированный SQL значительно отличается в этих случаях.Первый запрос генерирует следующее:

SELECT t0.id, t0.name FROM foo t0
WHERE NOT EXISTS (
    SELECT DISTINCT t2.TAG FROM tag t2, foo_tags t1
    WHERE (((t1.foo = t0.id) AND (t2.TAG = t1.tag)) AND ('blue' = t2.TAG)))

, в то время как запрос критерия генерирует это:

SELECT t1.id, t1.name FROM tag t0, foo_tags t2, Foo t1
WHERE (NOT ((t0.TAG = 'blue')) AND ((t2.foo = t1.id) AND (t0.TAG = t2.tag)))

Я проверял это только с помощью реализации eclipselink, поэтому, возможно, там есть проблемано я решил сначала спросить, заметит ли кто-нибудь очевидную ошибку.

1 Ответ

0 голосов
/ 17 мая 2011

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

Пожалуйста, зарегистрируйте ошибку для проблемы критериев в EclipseLink.

Вы должны иметь возможность использовать объединение или дополнительный выбор вместо специального члена синтаксиса.

SELECT f FROM Foo f left join f.tags t WHERE not(t == :tag)
...