Coleções do tipo Collection, List, Set, Map são umas das estruturas de dados mais utilizadas e o JPA permite seu mapeamento para o modelo relacional de forma simples e eficiente. Você só precisa utilizar as anotações adequadas e não se preocupar como as coleções estão sendo representadas no banco de dados! Vejamos os casos mais comuns de mapeamento de coleções, sejam as coleções classes de entidade, classes embutidas ou tipos básicos:
- Multiplicidade simples entre uma classe de entidade e classes não-entidade (classes embutidadas)
Exemplo: Uma empresa pode ter muitos endereços (Endereço aqui é uma classe embutida):
@Embeddable class Endereco{} @Entity class Empresa{ @ElementCollection Set<Endereco> enderecos; //para classes embutidas, utilize @ElementCollection. }Opcionalmente você pode especificar como o JPA deve gerar a tabela de coleções no banco de dados fornecendo alguns parâmetros:
@Entity class Empresa{ @Id int idEmpresa; @ElementCollection @CollectionTable(name="logradouro", joinColumns=@JoinColumn(name="emp_id")) @AttributeOverride(name="address", column=@Column(name="o_nome_q_vc_quiser")) Collection<Endereco> enderecos; }
No exemplo anterior, para representar a coleção de endereços da empresa, dissemos para o JPA criar uma tabela chamada logradouro. @JoinColumn representa a chave estrangeira.
Multiplicidade indexada (pares chave/valor)
Pares chave/valor são representados pela interface Map. Coleções desse tipo são muito comuns e são utilizadas em praticamente todas as aplicações. O JPA é bastante flexível com tipos Map. As entidades ou classes embutidas podem representar tanto a chave quanto o valor, ou ainda chave e valor podem ser tipos primitivos.
1 Chave e Valor são tipos primitivos
1 Chave e Valor são tipos primitivos
Exemplo: Um funcionário pode ter vários números de telefone e cada número é de um tipo (comercial, trabalho, casa, etc.):
Essencialmente você só precisa da usar a anotação @ElementCollection para resolver seu problema. Todas as outras são opcionais.
@Entity public class Funcionario{ @Id private int id; @ElementCollection @CollectionTable(name="funcionario_telefone") //opcional, define o nome da tabela no banco @MapKeyColumn(name="tipo_telefone") ///opcional indica qual coluna armazena achave @Column(name="numero") //nome da coluna que armazena o valor private Map<String, String> telefones; //... }2 A chave do Map pode ser uma enum ou uma data
public enum TipoTelefone {HOME, MOBILE, WORK} @Entity public class Funcionario{ @Id private int id; @ElementCollection @CollectionTable(name="funcionario_telefone") //opcional, define o nome da tabela no banco @MapKeyEnumerated(EnumType.STRING) @MapKeyColumn(name="tipo_telefone") ///opcional indica qual coluna armazena a chave @Column(name="numero") //nome da coluna que armazena o valor private Map<TipoTelefone, String> telefones; //... }Caso quisessemos usar como chave o tipo java.util.Date, poderíamos usar a anotação @MapKeyTemporal ao invés de @MapKeyEnumerated.
Exemplo: Um departamento tem vários cubículos cada qual com um funcionário.
A modelagem tradicional um departamento tem muitos funcionários ainda não atenderia eficazmente esse cenário. O software precisa indexar cubículo e funcionário.
4 Chave é o ID da própria entidade que representa o valor do MapA modelagem tradicional um departamento tem muitos funcionários ainda não atenderia eficazmente esse cenário. O software precisa indexar cubículo e funcionário.
@Entity public class Departamento{ @Id private int id; @ManyToMany @JoinTable(name="DEPT_EMP", joinColumns=@JoinColumn(name="DEPT_ID"), inverseJoinColumn=@JoinColumn(name="EMP_ID")) @MapKeyColumn(name="CUB_ID") private Map<String, Funcionario> funcionarioPorCubiculo; }
É comum e intuitivo indexar a chave do map pelo ID da entidade. No exemplo anterior o poderíamos usar algum atributo do funcionário como identificador do cubículo ao invés do próprio nome atribuído pelo departamento.
@Entity public class Departamento{ @Id private int id; @OneToMany(mappedBy="departamento") @MapKey(name="id") private Map5 Chave é uma entidade e valor é um tipo básicofuncionarios; }
Exemplo: Atribuir a senioridade de cada funcionário no departamento em um contexto onde o funcionário pode atuar em vários departamentos e a senioridade podendo variar, uma vez que ela é determinada em função do departamento (um funcionário pode ser pleno no setor de desenvolvimento e junior no departamento de infraestrutura...).
@Entity public class Department{ @Id private int id; @ElementCollectionn @CollectionTable(name="emp_senioridade") @MapKeyJoinColumn(name="emp_id") @Column(name="senioridade") private Map<Employee, Integer> seniorites; // ... }
No comments:
Post a Comment