<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.caelum.com.br &#187; hql</title>
	<atom:link href="http://blog.caelum.com.br/tag/hql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.caelum.com.br</link>
	<description>blog dos desenvolvedores da Caelum</description>
	<lastBuildDate>Thu, 09 Feb 2012 13:04:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Divisions com Hibernate: uso avançado da Criteria API</title>
		<link>http://blog.caelum.com.br/divisions-com-hibernate-uso-avancado-da-criteria-api/</link>
		<comments>http://blog.caelum.com.br/divisions-com-hibernate-uso-avancado-da-criteria-api/#comments</comments>
		<pubDate>Thu, 11 Sep 2008 12:57:00 +0000</pubDate>
		<dc:creator>Lucas Cavalcanti</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[banco de dados]]></category>
		<category><![CDATA[criteria]]></category>
		<category><![CDATA[detachedcriteria]]></category>
		<category><![CDATA[division]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[hql]]></category>
		<category><![CDATA[jpa]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/?p=316</guid>
		<description><![CDATA[Existe uma operação, não muito conhecida, mas muitas vezes necessária, em bancos de dados chamada divisão (division). Essa operação representa o seguinte tipo de consulta: Selecione os alunos que fizeram todos os cursos. Selecione os autores em que todos os seus livros têm mais de 200 páginas. E assim por diante. Esse tipo de consulta <a href="http://blog.caelum.com.br/divisions-com-hibernate-uso-avancado-da-criteria-api/#more-316'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Existe uma operação, não muito conhecida, mas muitas vezes necessária, em bancos de dados chamada  <strong>divisão</strong> (<em>division</em>). Essa operação representa o seguinte tipo de consulta: Selecione os alunos que fizeram todos os cursos. Selecione os autores em que <strong>todos</strong> os seus livros têm mais de 200 páginas. E assim por diante.</p>
<p>Esse tipo de consulta precisa de alguns recursos avançados do SQL, então antes de mostrar como implementá-la vamos ver como implementar consultas um pouco mais simples, usando a <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/Subqueries.html">Subqueries</a> e a <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/DetachedCriteria.html">DetachedCriteria</a>, que nos possibilitam consultas bastante poderosas usando a api da <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/package-frame.html">Criteria</a>.</p>
<p>Bom, vamos começar com três entidades: <code>Aluno</code>, <code>Curso</code>, e um relacionamento de muitos pra muitos entre eles representado pela entidade <code>Matrícula</code>.</p>
<p>Vamos pensar um pouquinho como fazer a seguinte consulta: &#8220;<em>Selecionar todos os alunos que estejam cursando <strong>Matemática</strong> ou <strong>Português</strong></em>&#8220;. Pensando em banco de dados, podemos fazer um <em>join</em> entre Alunos e Matrículas, e selecionar as linhas em que o curso é <strong>matemática</strong> ou é <strong>português</strong>. Precisamos também evitar que a busca retorne alunos repetidos. Vamos fazer isso com <code>Criteria</code>, recebendo a lista dos cursos que eu quero que o aluno esteja cursando algum deles: </p>
<pre class="brush: java; title: ; notranslate">
public List&lt;Aluno&gt; alunosCursandoAlgumDessesCursos(List&lt;Curso&gt; cursos) {
  Criteria criteria = session.createCriteria(Aluno.class);
  //join com as matrículas
  criteria.createCriteria(&quot;matriculas&quot;, &quot;m&quot;);

  //usando a disjunction para fazer um 'ou' entre vários elementos
  Disjunction ou = Restrictions.disjunction();
  for (Curso curso : cursos) {
    ou.add(Restrictions.eq(&quot;m.curso&quot;, curso);
  }
  criteria.add(ou);

  //eliminando resultados repetidos
  criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
  return criteria.list();
}
</pre>
<p>Ou podemos fazer algo bem mais interessante, que é usar a restrição <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/Restrictions.html#in(java.lang.String,%20java.util.Collection)">in</a>, que retorna verdadeiro se a propriedade dada é igual a algum dos elementos da coleção que passarmos pra ela. Nesse caso trocaríamos o <code>Disjunction</code> por simplesmente: </p>
<pre class="brush: java; title: ; notranslate">
criteria.add(Restrictions.in(&quot;m.curso&quot;, cursos));
</pre>
<p>Bem fácil! Agora vamos mudar só um pouquinho a consulta para: &#8220;<em>Selecione todos os alunos que estiverem cursando Português <b>E</b> Matemática</em>&#8220;. Poderíamos inocentemente mudar a <code>Disjunction</code> para <code>Conjunction</code> no método anterior. Mas isso não funciona! Por quê? Porque se fizermos isso, estaríamos mudando a consulta para algo do tipo: &#8220;<em>Selecione os alunos que tenham uma matrícula que é em Português e em Matemática ao mesmo tempo</em>&#8220;. E isso não é possível. Temos que mudar essa consulta para algo do tipo: &#8220;<em>Selecione todos os alunos para os quais exista uma matricula no curso Português e exista uma matrícula no curso Matemática</em>&#8220;.</p>
<p>Existe uma operação em SQL que faz exatamente isso: o <b>exists</b>. Ela retorna verdadeiro se a subconsulta que estiver depois dela retornar algum resultado. Para fazer isso precisamos então criar subconsultas em <code>Criteria</code>, e o jeito de fazer isso é usando a classe <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/Subqueries.html">Subqueries</a>, que fabrica <code>Criterions</code> que envolvem a criação de subconsultas.</p>
<p>Para usar qualquer método da Subqueries precisamos de uma <a href="http://www.hibernate.org/hib_docs/v3/api/org/hibernate/criterion/DetachedCriteria.html">DetachedCriteria</a>. Essa <code>DetachedCriteria</code> é um tipo especial de <code>Criteria</code> que não precisa da session do hibernate para ser criada. Dentro dela temos acesso a todos os alias e propriedades da <code>Criteria</code> principal, e o uso é o mesmo que faríamos para Criterias normais.</p>
<p>Já que temos a Subqueries na mão, vamos implementar a consulta, recebendo a lista dos cursos que queremos que o aluno esteja matriculado em todos eles:</p>
<pre class="brush: java; title: ; notranslate">
public List&lt;Aluno&gt; alunosCursandoTodosEssesCursos(List&lt;Curso&gt; cursos) {
  Criteria criteria = session.createCriteria(Aluno.class, &quot;a&quot;);
  Conjunction e = Restrictions.conjunction();
  for (Curso c : cursos) {
    e.add(Subqueries.exists(
      DetachedCriteria.forClass(Matricula.class, &quot;m&quot;)
        .setProjection(Projections.id())
        .add(Restrictions.eqProperty(&quot;a.id&quot;, &quot;m.aluno.id&quot;))
        .add(Restrictions.eq(&quot;m.curso&quot;,c))));
  }
  criteria.add(e);
  return criteria.list();
}
</pre>
<p>Ou seja, queremos que exista uma matrícula do aluno da <code>Criteria</code> principal para cada curso da lista passada.</p>
<p>Mas vamos pensar no seguinte: Essa lista de cursos provavelmente veio de outra consulta no banco, por que não usar essa consulta, ao invés da lista de cursos?! O jeito de fazer isso é usando o operador division que falamos no começo do post. Ele é meio complicado de implementar, pois você tem que pensar meio ao contrário do normal. Por exemplo, para implementar a consulta &#8220;<em>Selecione os alunos que estão matriculados em todos os cursos</em>&#8221; precisamos transformá-la para: &#8220;<em>Selecione os alunos para os quais não exista nenhum curso para o qual não exista matrícula desse aluno para esse curso</em>&#8220;, ou seja: um aluno que não exista nenhum curso em que ele não esteja matriculado. É estranho mas é assim mesmo que é feito. A Subqueries também possui o método <code>notExists</code>, então podemos fazer a seguinte consulta, que traz os alunos que fazem todos os cursos:</p>
<pre class="brush: java; title: ; notranslate">
public List&lt;Aluno&gt; alunosCursandoTodosOsCursos() {
  Criteria criteria = session.createCriteria(Aluno.class, &quot;a&quot;);
  criteria.add(Subqueries.notExists(
      DetachedCriteria.forClass(Curso.class, &quot;c&quot;)
        .setProjection(Projections.id())
        .add(Subqueries.notExists(
            DetachedCriteria.forClass(Matricula.class, &quot;m&quot;)
              .setProjection(Projections.id())
              .add(Restrictions.eqProperty(&quot;m.curso.id&quot;, &quot;c.id&quot;))
              .add(Restrictions.eqProperty(&quot;m.aluno.id&quot;, &quot;a.id&quot;)
        ))
      ));
  return criteria.list();
}
</pre>
<p>Não é um bicho de sete cabeças, mas também não é nada trivial. O código fica meio poluído por causa das chamadas estáticas, mas se você fizer o <code>import static</code> dos métodos a coisa melhora um pouquinho.</p>
<p>As restrições que você tinha colocado para buscar a lista de cursos dos métodos anteriores, você pode colocar na <code>DetachedCriteria</code> de<code> Cursos</code>, que vai funcionar do jeito que é esperado. Por exemplo: &#8220;<em>Selecione os alunos que estejam matriculados em um curso noturno</em>&#8221; vira &#8220;<em>Selecione os alunos para os quais não exista algum curso noturno em que ele não esteja matriculado</em>&#8220;. Mais ainda: você pode colocar restrições pertinentes na <code>DetachedCriteria</code> da matrícula, que também vai funcionar da forma esperada. Por exemplo: &#8220;<em>Selecione os alunos que estejam com a matricula paga em todos os cursos</em>&#8221; vira &#8220;<em>Selecione os alunos para os quais não existe algum curso em que não exista matrícula paga nesse curso</em>&#8220;. </p>
<p>Existem muitos casos em que o operador division salva sua vida então, mesmo que ele seja meio complicadinho, é bom saber que ele existe e ter uma boa referência de como implementá-lo =).</p>
<p>Além da Subqueries, existe outra classe muito útil que fabrica <code>Criterion</code>s e <code>Projection</code>s relacionados a uma propriedade fixa: a <a href="http://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/criterion/Property.html">Property</a>. Vale a pena olhar o javadoc do hibernate e ver a quantidade de opções de consultas que temos disponíveis. Existe <a href="http://opensource.atlassian.com/projects/hibernate/browse/HHH-993">um bug</a> no hibernate que te obriga a setar uma <code>Projection</code> nas <code>DetachedCriterias</code> quando usadas dentro das Subqueries, se isso não é feito o hibernate nos presenteia com uma <code>NullPointerException</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/divisions-com-hibernate-uso-avancado-da-criteria-api/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>JPA com Hibernate: Herança e Mapeamentos</title>
		<link>http://blog.caelum.com.br/jpa-com-hibernate-heranca-e-mapeamentos/</link>
		<comments>http://blog.caelum.com.br/jpa-com-hibernate-heranca-e-mapeamentos/#comments</comments>
		<pubDate>Sun, 04 Mar 2007 07:25:01 +0000</pubDate>
		<dc:creator>Paulo Silveira</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[fj-25]]></category>
		<category><![CDATA[herança]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[hql]]></category>

		<guid isPermaLink="false">http://blog.caelum.com.br/2007/03/04/jpa-com-hibernate-heranca-e-mapeamentos/</guid>
		<description><![CDATA[Essas semanas postarei algumas dicas rápidas no uso da JPA com Hibernate. São alguns pontos que sempre aparecem no desenvolvimento, referentes a performance, elegância e facilidades. Alguns tópicos já são de amplo conhecimento dos usuários do Hibernate, porém na JPA alguns deles são utilizados diferentemente. Cuidado com herança por InheritanceType.JOINED Aqui na Caelum, conforme discutido <a href="http://blog.caelum.com.br/jpa-com-hibernate-heranca-e-mapeamentos/#more-105'" class="more-link">more &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Essas semanas postarei algumas dicas rápidas no uso da JPA com Hibernate. São alguns pontos que sempre aparecem no desenvolvimento, referentes a performance, elegância e facilidades. Alguns tópicos já são de amplo conhecimento dos usuários do Hibernate, porém na JPA alguns deles são utilizados diferentemente.</p>
<p><strong>Cuidado com herança por <code>InheritanceType.JOINED</code></strong></p>
<p>Aqui na Caelum, <a href="http://blog.caelum.com.br/jpa-com-hibernate-heranca-e-mapeamentos/">conforme discutido anteriormente</a>, usamos herança com muito critério. Herança na JPA é mapeada com <code>@Inheritance(strategy=InheritanceType.SINGLE_TABLE)</code> por padrão, isto é, ele vai utilizar uma única tabela para guardar todos os dados de todas as classes filhas: não há normalização e uma coluna (o <code>discriminator</code>, por default <code>DTYPE</code> no Hibernate) será utilizada para distinguir entre as possíveis subclasses.</p>
<p>Muitos administradores de banco de dados reclamam dessa estratégia, sendo que a mais elegante é a <code>InheritanceType.JOINED</code>, onde cada classe terá uma tabela, mas sem repetir colunas. As tabelas que representam as classes filhas possuem uma chave estrangeira para a tabela que representa a mãe, normalizando o banco nesse aspecto.</p>
<p>O grande problema dessa estratégia são as queries polimórficas: no caso de você possuir uma classe mãe <code>Pessoa</code> e duas filhas <code>PessoaFisica</code> e <code>PessoaJuridica</code>, ao procurar por uma <code>Pessoa</code> pela sua chave primária o hibernate vai gerar um join entre <strong>todas</strong> essas tabelas (pode variar um pouco de acordo com o dialeto usado), já que não possuímos o <code>discriminator</code> nesse caso. </p>
<p><strong>Mapear resultados em vez de trabalhar com <code>List&lt;Object[]&gt;</code></strong></p>
<p>Se executamos uma Query em que nosso select não escolhe apenas um tipo de valor a ser retornado, recebemos uma <code>List&lt;Object[]&gt;</code> como resultado. Por exemplo, um <code>select e1.atributoInteiro, e2.atributoString from Entidade1 as e1, Entidade2 as e2 where...</code> retornaria uma <code>List&lt;Object[]&gt;</code> em que, para cada item da lista, a primeira posição da array é um <code>Integer</code> referente ao <code>atributoInteiro</code> da <code>Entidade1</code> e a segunda posição é uma <code>String</code> referente ao <code>atributoString</code> da <code>Entidade2</code>.</p>
<p>Tanto a JPA quanto o Hibernate permitem retornar qualquer tipo de objeto através da <a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html#queryhql-tuple">clausula de select, utilizando um construtor</a>. Podemos mudar a query anterior para <code>select new br.com.caelum.Bean(e1.atributoInteiro, e2.atributoString) from Entidade1 as e1, Entidade2 as e2 where...</code> para receber um <code>List&lt;AlgumBean&gt;</code> como resultado, desde que a classe <code>br.com.caelum.AlgumBean</code> possua um construtor que receba um <code>Integer</code> e uma <code>String</code>. Muito mais elegante que precisar percorrer uma <code>List&lt;Object[]&gt;</code> e encher nosso código de castings. Excelente parar gerar relatórios e já devolver os dados organizados em beans específicos.</p>
<p>Para mapeamentos mais avançados o Hibernate possui a interface <code>ResultTransformer</code> e sua factory <code>Transformers</code>. A JPA define a <code>SQLResultSetMapping</code> e outras anotações, mas para o uso de native queries.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.caelum.com.br/jpa-com-hibernate-heranca-e-mapeamentos/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>

