Нужно конвертировать левое соединение в JPQL - PullRequest
1 голос
/ 15 сентября 2011

представьте себе следующую проблему: кто-то хочет купить корзину с фруктами, содержащими зеленые фрукты из Африки и Южной Америки, но без красных фруктов из Африки.

, для этого мы думаем о следующих классах:



    class Basket
    {
      int id;
      Collection<Fruit> fruits; 
    }

    class Fruit
    {
      int id;
      int basketId;
      String origin
      Color color;
    }

отображение будет MxM.Предполагается, что Fruit не имеет объекта Basket, но при необходимости я мог бы реализовать его.

для нативного SQL, я бы использовал:



    SELECT * 
    FROM 
      Basket b 
    JOIN 
    (
      SELECT DISTINCT basketId 
      FROM Fruit 
      WHERE color='green' AND (origin='Africa' OR origin='South America')
    ) f1 ON (b.id=f1.basketId) 
    LEFT JOIN 
    (
      SELECT DISTINCT basketId 
      FROM Fruit 
      WHERE color='red' AND (origin='Africa')
    ) f2 ON (b.id=f2.basketId) 
    WHERE f2.basketId IS NULL 

Каким будет запрос в JPQL?

я уже пробовал следующее:



    SELECT b 
    FROM Basket b 
    WHERE 
      b.id IN (
        SELECT f1.basketId FROM Fruit f1 
        WHERE f1.color='green' AND (f1.origin='Africa' OR f1.origin='South America')
      ) AND
      b.id NOT IN (
        SELECT f2.basketId FROM Fruit f2 
        WHERE f2.color='red' AND (origin='Africa'))

, но этот запрос занял 12000мс вместо 50 мс.(Это простой пример. Реальные таблицы содержат около 750000 «фруктов» и 10000 «корзин» с гораздо большим количеством полей в каждом.)

Заранее спасибо

Джеральд

Ответы [ 2 ]

0 голосов
/ 15 сентября 2011

будет ли это работать?

select b from Basket b join b.fruits f where f.color = 'green' and not f.color = 'red';

Объединение, вероятно, необязательно, поэтому оно также может быть

select b from Basket b where b.fruits.color = 'green' and not b.fruits.color = 'red';
0 голосов
/ 15 сентября 2011

Вы можете попробовать

select b from Basket b where
    exists (select f.id from Fruit f where f.basket = b and f.color = 'green')
    and not exists (select f.id from Fruit f where f.basket = b and f.color = 'red')

Но я не уверен, что это будет быстрее. Это зависит от плана выполнения, который зависит от индексов базы данных. Должен быть индекс на Fruit.basketId и на Fruit.color.

...