Não há dúvidas de que o hibernate é um excelente ORM, se não o melhor que há no mercado. Porém, muitas pessoas, satisfeitas com os procedimentos iniciais de aprendizado do framework, não se dão conta das demais funcionalidades disponíveis para o desenvolvedor. A lista é vasta, confesso que posso não conhecer a metade, mas alguns dias atrás, uma dessas funcionalidades me ajudou muito.
Um objeto persistente, para o hibernate, é uma entidade que contem relacionamentos com outras entidades que juntos formam uma relação. Em diversas situações, na maioria das vezes no mundo real, essa relação se torna complexa quando existe a necessidade de relação com outras entidades, somado com o numero enorme de dados relacionados. Existem várias formas de obter essas esses dados relacionados, uns que permitem obter todo o conjunto de dados relacionados ao carregar o objeto (eager), outro no momento que a relação é obtida (lazy). Outras alternativas podem ser utilizadas em conjunto, como, as consultas nomeadas atreladas ao carregamento do objeto. Porém, apenas obter a lista de desses informações não é suficiente para a aplicação, fazendo com que o desenvolvedor utiliza consultas mais elaboradas com HQL ou criteria.
A forma como o framework monta as consultas é na maioria das vezes genérica e pouco intuitiva, fazendo com que o desenvolvedor opte por utilizar o SQL nativo, ou portar a consulta para uma Stored Procedure para construir uma consulta mais elaborada. É uma estratégia plausível quando a aplicação necessita de desempenho mas, isso tiraria a principal vantagem do framework; o acesso as relações que são representadas pelo relacionamento entre os objetos. Existe uma maneira muito simples de executar uma consulta SQL mantendo o relacionamento entre os objetos.
Para o framework, os objetos persistentes são de extrema importância. Quando o framework é executado pela primeira vez, ele adiciona uma série de funcionalidade nos objetos persistentes que permite realizar as operações em suas relações. A maneira com que o framework realiza essa tarefa é pela Instrumentação de código. A instrumentação nada mais de uma técnica de incluir alterações do código do programa mesmo após a sua compilação. O conceito pode ser semelhante com Reflexão e AOP, mas existem particularidades que tornam os conceitos bem distintos. Por ser um assunto muito pesquisado e com referencias em abundância, é um assunto para ser tratado outra hora. No hibernate, isso é feito através da lib ASM, que é um extenso conjunto de utilidade que permitem a plicar esse conceito nas classes escritas em linhagem Java.
Bom, para que o framework compreenda que o resultado de uma consulta SQL possa ser vinculado a um objeto é necessário que o retorno corresponda aos atributos do objeto, sendo que o objeto possa ser reconhcido pelo motor de consulta. Ex:
List<ClasseQualquer> planos = new ArrayList<ClasseQualquer>();
String queryStr = queryUtils.findValue(nome_da_query); //obtem a string de consulta
Query query = entityManager.createNativeQuery(queryStr, ClasseQualquer.class);
Obtendo um objeto Query configurado como acima, é possível realizar operações como essas abaixo:
List dados = instanciaObjetoQualquer.getDadosParticulares();
Esse simples macete pode ajudar bastente para obter objetos, que necessitem manter o acesso aos objetos relacionados, através de consultas bem elaboradas e com o desempenho do SQL.