Mapeando Coleções com Hibernate

por:
 

Raphaela Galhardo (raphaela@jeebrasil.com.br)
Gleydson Lima (gleydson@jeebrasil.com.br)
 

Este tutorial apresenta o mapeamento de coleções usando o Hibernate.

 

Introdução

O mapeamento de coleções já foi apresentado nos tutoriais sobre associações. Essa seção está destinada a apresentar o mapeamento dos quatro tipos de coleções existentes: Set, Bag, List e Map.

Set

Um Set é um conjunto que contém elementos únicos. Como já citado, o seu mapeamento é feito através da tag set e possui o conjunto de atributos mostrado na Listagem 1. Esses atributos são semelhantes para os demais tipos de coleções a serem apresentadas.

<set
   name="nomePropriedade”
   table="nomeTabela"
   schema="nomeEsquema"
   lazy="true|false"
   inverse="true|false"
   cascade="all|delete|save-update|delete|delete-orphan|all-delete- 
            orphan"
   sort="unsorted|natural|comparatorClass"
   order-by="nome_coluna asc|desc"
   where="condição sql arbitrária">
      <key .../>
      <element .../> | <one-to-many .../> | <many-to-many .../>
</set>

Listagem 1 - - Coleções: Atributos

Dos atributos ainda não apresentados nos tutoriais sobre associações estão:

  • schema: indica o nome do esquema do banco de dados;
  • sort: a ordenação pode ser feita na classe Java.
    • unsorted: desordenada
    • natural: odenada a partir do método equals(...);
    • comparatorClass: ordenada a partir do método compareTo();
  • order-by: ordenação feita no banco de dados a partir do nome da coluna informada. Pode ser ascendente ou descendente;
  • where: para informar uma condição arbitrária para a busca da coleção.
  • element: indica que a coleção é formada por um tipo primitivo.

Exemplos de Set já foram apresentados nos mapeamentos dos relacionamentos. Para exemplificar o mapeamento de um Set de tipos primitivos considere o mapeamento de uma coleção de String’s para armazenar os telefones de um Aluno, como visto na Figura 1. Então no mapeamento Aluno.hbm.xml deve ser inserido o mapeamento mostrado na Listagem 2.

JSP

Figura 1 - Coleção de telefones para Aluno

...
<set name="telefones" lazy="true" table="ALUNO_TELEFONE">
   <key column="ID_ALUNO"/>
   <element type="java.lang.String" 
          column="TELEFONE" not-null="true"/>
</set>
...

Listagem 2 - Coleções: Set

Os telefones do aluno são armazenados na tabela ALUNO_TELEFONE. Para o banco de dados está tabela é separada da tabela ALUNO, mas para o Hibernate, ele cria a ilusão de uma única entidade. A tag key indica a chave estrangeira da entidade pai (ID_ALUNO). A tag element indica o tipo da coleção (String) e a coluna na qual está a informação.

Um Set não pode apresentar elementos duplicados, portanto a chave primária de ALUNO_TELEFONE consiste nas colunas ID_ALUNO e TELEFONE.

Dado o mapeamento da coleção de telefones de Aluno, observe o exemplo mostrado na Listagem 3. Neste exemplo, cria-se um objeto Aluno que terá o seu nome definido e um único número de telefone inserido em sua coleção de String’s. Por fim, o objeto Aluno é persistido. O resultado é mostrado na Listagem 4, onde primeiro é inserida uma linha na tabela ALUNO e posteriormente uma linha na tabela ALUNO_TELEFONE.

Aluno aluno = new Aluno();
aluno.setNome("João Maria Costa Neto");
aluno.setTelefones(new HashSet());
aluno.getTelefones().add("32222529");
		
session.save(aluno);

Listagem 3 - Exemplo de Mapeamento de Set

Hibernate: insert into ALUNO (MATRICULA, NOME, CPF, 
           ID_CURSO, ID_ALUNO) values (?, ?, ?, ?, ?)
Hibernate: insert into ALUNO_TELEFONE (ID_ALUNO,        
           TELEFONE) values (?, ?)

Listagem 4 - Resultado da execução do código presente na Listagem 3

List

Um List é uma coleção ordenada que pode conter elementos duplicados. O mapeamento de uma lista requer a inclusão de uma coluna de índice na tabela do banco de dados. A coluna índice define a posição do elemento na coleção, como visto na Figura 2 no mapeamento da coleção de telefones da entidade Aluno como sendo um List. Dessa maneira, o Hibernate pode preservar a ordenação da coleção quando recuperada do banco de dados e for mapeada como um List. Observe o mapeamento da coleção telefones na Listagem 5.

JSP

Figura 2 - Coleção de telefones para Aluno: List

...
<list name="telefones" lazy="true" table="ALUNO_TELEFONE">
   <key column="ID_ALUNO"/>
   <index column="POSICAO"/>
   <element type="java.lang.String" 
          column="TELEFONE" not-null="true"/>
</list >
...

Listagem 5 – Coleções: List

Mapeando a coleção como um List, a chave primária da tabela ALUNO_TELEFONE passa a ser as colunas ID_ALUNO e POSICAO, permitindo a presença de telefones (TELEFONE) duplicados na coleção.

Maps

Maps associam chaves aos valores e não podem conter chaves duplicadas. Eles diferem de Sets no fato de que Maps contêm chaves e valores, ao passo que Sets contêm somente a chave.

O mapeamento de um Map é semelhante ao de um List, onde o índice de posição passa a ser a chave. Veja a Figura 3. A Listagem 6 apresenta a coleção de telefones sendo mapeada como um Map. A chave primária da tabela ALUNO_TELEFONE passa a ser as colunas ID_ALUNO e CHAVE, também permitindo a presença de telefones duplicados na coleção.

JSP

Figura 3 - Coleção de telefones para Aluno: Map

...
<map name="telefones" lazy="true" table="ALUNO_TELEFONE">
   <key column="ID_ALUNO"/>
   <index column="CHAVE" type="java.lang.String"/>
   <element type="java.lang.String" 
          column="TELEFONE" not-null="true"/>
</map>
...

Listagem 6 – Coleções: Map

Bag

Um Bag consiste em uma coleção desordenada que permite elementos duplicados. Em Java não há implementação de um Bag, contudo o Hibernate fornece um mecanismo de que um List em Java simule o comportamento de um Bag. Pela definição de um List, uma lista é uma coleção ordenada, contudo o Hibernate não preserva a ordenação quando um List é persistido com a semântica de um Bag. Para usar o Bag, a coleção de telefones deve ser definida com o tipo List. Um exemplo de mapeamento de um Bag pode ser visto na Figura 4 e Listagem 7.

JSP

Figura 4 - Coleção de telefones para Aluno: Bag

Para simular o Bag como List, a chave primária não deve ter associação com a posição do elemento na tabela, assim ao invés da tag index, utiliza-se a tag collection-id, onde uma chave substituta diferente é atribuída a cada linha da tabela na coleção. Entretanto, o Hibernate não fornece nenhum mecanismo para descobrir o valor chave substituta de uma linha em particular.

...
<idbag name="telefones" lazy="true" table="ALUNO_TELEFONE">
   <collection-id type="long" column="ID_ALUNO_TELEFONE">
      <generator class="sequence"/>
   </collection-id>
   <key column="ID_ALUNO"/>
   <element type="java.lang.String" 
          column="TELEFONE" not-null="true"/>
</idbag>
...

Listagem 7 - Coleções: Bag

Conclusões

Neste tutorial foram apresentados os mapeamentos de coleções (Bag, Map, List, Set) usando o Hibernate. No próximo tutorial será apresentado o mapeamento de herança utilizando três estratégias distintas: tabela por classe concreta, tabela por hierarquia, tabela por sub-classe. Neste tutorial foram apresentados os mapeamentos de coleções. O próximo tutorial trará o mapeamento de herança, abordando três estratégias distintas.

Referências

  1. Christian Bauer e Gavin King. Hibernate in Action. 2005.
  2. Grupo Hibernate. Hibernate Reference Documentation. Version 3.0.5. Obtido em http://www.hibernate.org
  3. Gleydson de Azevedo Ferreira Lima. Material Didático. 2005.
  4. Nick Heudecker. Introdução ao Hibernate.
  5. Maurício Linhares. Introdução ao Hibernate 3.
  6. Francesc Rosés Albiol. Introducción a Hibernate. 2003.
  7. Fabiano Kraemer, Jerônimo Jardel Vogt. Hibernate, um Robusto Framework de Persistência Objeto-Relacional. 2005.

 

Free Web Hosting