Olá,
O mapeamento de relacionamentos c/ JPA já traz definido a estratégia de fetching (lazy/eager), por padrão, no caso das annotations para coleções. Isso pode ser sobrescrito, via atributo “fetch”, e ainda “aprimorado”, com annotations específicas do Hibernate (caso ele seja o seu persistence provider).
Esse debate de inicialização de relacionamentos em tempo de execução é antigo, e separa a maioria dos desenvolvedores em duas “trincheiras”: Uns defendem que é preciso desenvolver mecanismos de “fetching transparente”, ou seja, o próprio hibernate inicializa relacionamentos lazy quando eles são requeridos, abrindo uma nova sessão se for necessário. Outros, com os quais eu particularmente concordo, defendem que a responsabilidade de inicializar relacionamentos é do próprio desenvolvedor, em seu caso de uso.
Usar o left join é uma boa; Você busca os objetos no grafo no momento em que precisa deles, e usa apenas proxies de objetos em memória na maior parte do tempo. Entretanto, quando você não tem o luxo de efetuar uma busca na camada onde está programando, o jeito é apelar pela inicialização via Hibernate.initialize(), uso de uma sessão corrente (e abertura/manutenção de uma nova, caso necessário), e outros recursos.
Uma proposta interessante que surgiu entre os que defendem que a inicialização deve ser transparente é o =http://h3t.sourceforge.net/H3T. Mas ele tem problemas que você vai identificar assim que tentar usar (i.e, uso “duvidoso” de AOP). Além de ser um projeto com baixa atividade, sem test cases maduros, etc…
Rodrigo