Выполнить запрос “ЭЛЕМЕНТ” к полям карты "ElementCollection" в JP-QL (JPA 2.0)
-
20-09-2019 - |
Вопрос
Можно ли запустить запрос "ЧЛЕН" к ассоциативным массивам?Если да, то как выглядит синтаксис?Очевидным обходным путем является собственный запрос, но это становится довольно запутанным из-за всех объединений и тому подобного.Я хотел бы проверить наличие объекта в наборе ключей карты, коллекции значений или наборе записей.Может быть, что-то вроде следующего:
SELECT p FROM Person p WHERE 'home' MEMBER OF p.phoneNumbers.keySet
SELECT p FROM Person p WHERE '867-5309' MEMBER OF p.phoneNumbers.values
SELECT p FROM Person p WHERE {'home' -> '867-5309'} MEMBER OF p.phoneNumbers
Код, не зависящий от поставщика, может быть слишком большим, чтобы требовать;поддерживает ли это Eclipselink?
Решение
В JPQL есть функция с именем index()
что полезно для получения индекса в @OrderColumn
Список.И, как вы сами сказали, карты также называются ассоциативными массивами, а ключи карты соответствуют индексам массива.Так что ничто не мешает index()
от возврата ключа записи на карте.
Этот запрос отлично работает в режиме гибернации:
SELECT p FROM Person p, in (p.phoneNumbers) number
WHERE number = '867-5309' AND index(number) = 'home'
Другие советы
Это должно сработать:
SELECT p FROM Person p
WHERE (select count(*) from p.phoneNumbers where name='home' and value='867-5309') > 0
Следующий запрос работает для меня:
select model from AnsOutboxMsg model
left join fetch model.updateEntity upde
left join fetch upde.update upd
left join fetch model.ansMessage msg
left join fetch msg.template msgt
left join fetch msg.ansAction act
left join fetch act.ansRule rl
left join fetch rl.app app
where (select count(*) from model.contextMap where name = 'fltClient' and value = 'XXX') > 0 and model.status = 'sent' and app.id = 'SPN_TICKETS' and msgt.name = 'Client' order by model.modifDate DESC, model.id ASC
Спецификация JPA(2) не определяет свой синтаксис для Карта используйте в MEMBER OF (изначально вы имели в виду массивы, но я не вижу релевантности, если у вас есть map), следовательно, вы не можете полагаться на какой-либо синтаксис, допустимый для всех реализаций JPA.Поскольку JPQL не поддерживает методы Java, такие как keySet, значения, то я не вижу, чтобы они были вероятными.Более чем вероятно, что он будет поддерживать только проверку на существование значения, например
'867-5309' MEMBER OF p.phoneNumbers
Для справки, в JDOQL вы бы сделали
p.phoneNumbers.containsKey('home');
p.phoneNumbers.containsValue('867-5309');