Execute os campos de mapa "Membro da" contra o "elemento elementCollection" no JP-QL (JPA 2.0)
-
20-09-2019 - |
Pergunta
É possível executar um "membro da consulta" contra matrizes associativas? Se sim, como é a sintaxe? A solução óbvia é uma consulta nativa, mas isso fica muito confuso com todas as junções e coisas do tipo. Gostaria de testar a existência de um objeto no conjunto de chaves, coleta de valores ou conjunto de entrada do mapa. Talvez algo como o seguinte:
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
O código agnóstico do provedor pode ser demais; O Eclipselink suporta isso?
Solução
JPQL tem uma função nomeada index()
o que é útil para obter o índice em um @OrderColumn
Lista. E, como você disse, os mapas também são chamados de matrizes associativas e as teclas de mapa correspondem a índices de matriz. Então, nada impede index()
de retornar a chave de uma entrada de mapa.
Esta consulta funciona perfeitamente no Hibernate:
SELECT p FROM Person p, in (p.phoneNumbers) number
WHERE number = '867-5309' AND index(number) = 'home'
Outras dicas
Deve funcionar:
SELECT p FROM Person p
WHERE (select count(*) from p.phoneNumbers where name='home' and value='867-5309') > 0
A próxima consulta funciona para mim:
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
A especificação JPA (2) não define sua sintaxe para um Mapa Use no membro de (você estava se referindo originalmente às matrizes, mas não vejo a relevância se tiver um mapa), consequentemente, não pode confiar em nenhuma sintaxe válida para todas as implementações da JPA. Como o JPQL não suporta métodos Java como o Keyset, os valores, então não consigo ver que eles são prováveis. Mais do que provável, ele só apoiará o cheque para uma existência de valor, como
'867-5309' MEMBER OF p.phoneNumbers
Para referência, em JDOQL, você faria
p.phoneNumbers.containsKey('home');
p.phoneNumbers.containsValue('867-5309');