2009-10-10 6 views
4

Возможно ли запустить запрос «ЧЛЕН» из ассоциативных массивов? Если да, то как выглядит синтаксис? Очевидным обходным решением является собственный запрос, но это становится довольно грязным, что со всеми объединениями и т. Д. Я бы хотел проверить наличие объекта в наборе ключей карты, наборе значений или наборе записей. Возможно, что-то вроде следующего:Выполнение запроса «ЧЛЕН» из полей «ElementCollection» в JP-QL (JPA 2.0)

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 это?

+0

Какого типа p.phoneNumbers? – DataNucleus

+0

Атрибут сущности типа «Карта <Строка, Строка>». –

ответ

8

JPQL имеет функцию с именем index(), которая полезна для получения индекс в списке @OrderColumn. И, как вы сказали сами, карты также называются ассоциативными массивами, а ключи карт соответствуют индексам массива. Поэтому ничто не препятствует возврату ключа записи карты index().

Этот запрос работает отлично на спящем режиме:

SELECT p FROM Person p, in (p.phoneNumbers) number 
WHERE number = '867-5309' AND index(number) = 'home' 
+0

key() следует использовать для карты, а не индекса() – James

+0

@James Я не знал о 'key()', но протестировал 'index()', и он работает. – Saintali

1

Спецификация JPA (2) не определяет его синтаксис для Map Использование в MEMBER OF (вы ссылались первоначально на массивы, но я не вижу релевантности, если у вас есть карта), следовательно, вы можете 't полагаться на любой синтаксис, действительный для всех реализаций JPA. Поскольку JPQL не поддерживает Java-методы, такие как keySet, значения, то я не вижу, что они вероятны. Более чем вероятно, он будет поддерживать только чек на существование значения, как

'867-5309' MEMBER OF p.phoneNumbers 

Для справки, в JDOQL, вы могли бы сделать

p.phoneNumbers.containsKey('home'); 
p.phoneNumbers.containsValue('867-5309'); 
4

Он должен работать:

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 
+0

+1 для презентации – Stephan