O Eclipselink gera um plano cartesiano em vez de (interno) se une ao SQL. Por quê?
-
20-09-2019 - |
Pergunta
Nos projetos em que o Hibernate é o meu provedor de persistência, posso emitir consultas com expressões de 'ingressar na busca', e o Hibernate gerará o SQL que reflete isso: SQL contendo expressões de junção usando caminhos válidos de comparação.
O Eclipselink, no entanto, emite o SQL com planos cartesianos feios, que prejudicam muito o desempenho. Ao ler isso artigo , ele menciona que buscar ansiosamente os planos cartesianos, mas esquece convenientemente que outros provedores (hibernados) podem otimizar isso.
Então, é possível instruir o Eclipselink para otimizar essas consultas? Acredito que poucos relacionamentos podem ser otimizados através do uso da anotação @FetchJoin, mas espero encontrar algo que não inclua a divulgação de anotações específicas do ORM no modelo de domínio.
Como exemplo, aqui está uma consulta (dinâmica) que estou emitindo como JPQL:
String query = "select w from WorkOrder w " +
"inner join fetch w.type " +
"inner join fetch w.details " +
"inner join fetch w.project " +
"inner join fetch w.priority " +
"inner join fetch w.networkElement ";
E aqui está a saída Eclipselink:
SELECT t1.ID, t1.CREATION, ... (the fetch fields here)
FROM swa_network_element t5, swa_priorities t4, swa_dispatch_project t3, swa_work_order_detail t2, swa_work_orders t1, swa_work_order_type t0
WHERE ((t1.alpha_id LIKE '%TSK%') AND (((((t0.ID = t1.TYPE_ID) AND (t2.worder_id = t1.ID)) AND (t3.id = t1.project_id)) AND (t4.ID = t1.priority_id)) AND (t5.ID = t1.ne_id))) ORDER BY t1.CREATION DESC
Atenciosamente, Rodrigo Hartmann
Solução
Tente usar:
@org.eclipse.persistence.annotations.JoinFetch(JoinFetchType.INNER)
-- ou --
@org.eclipse.persistence.annotations.JoinFetch(JoinFetchType.OUTER)
As junções externas são recomendadas para colunas anuláveis.
Encontrei mais informações neste blog: http://vard-lokkur.blogspot.com/2010/09/jpa-demystified-episode-1-enetomany-and.html
Cumprimentos,
Victor Tortorello Neto
Outras dicas
Não tenho certeza do que você quer dizer? O SQL parece correto, há uma junção para cada tabela, qual tabela está faltando uma junção?
Qual é o SQL que você está esperando?
Se você quer dizer colocar a condição de junção na cláusula From, em vez da cláusula WHERE, o EclipSELink faz isso para as junções externas, como é necessário, mas não é para junções internas, pois não faz diferença em nenhum banco de dados que eu conheço. Se você realmente deseja, pode configurar o EclipSELink 2.4 para imprimir a condição de junção para junções internas na cláusula From usando a API do DatabasePlatform SetPrintInnerJoinInwhereClause (false), mas não deve ter impacto no que o banco de dados faz.
A postagem do blog falando sobre ingressar na busca de questões cartesianas é quando você ingressa em vários relacionamentos de 1 m, isso pode fazer com que muitos dados sejam devolvidos. Não há como otimizar isso com a busca de junção, pois você precisa de todos os dados. No Eclipselink, você pode usar a busca de lote, o que é muito mais eficiente do que a busca.
Ver,http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html