Como criar relacionamento OneToMany com Hibernate

Olá, pessoal! No artigo de hoje, vou mostrar como criar o relacionamento oneToMany/ ManyToOne de uma forma bem simples. Afinal, quem nunca passou por algum tipo de problema ao criar esse tipo de relacionamento? Algo como de não criar a FK e só persistir uma das tabelas etc. Vou focar em como definir os relacionamentos no nível do código e, para isso, teremos code apenas para o objetivo do artigo. A minha intenção é evitar que os artigos fiquem grandes e cansativos. 

Required

Vou presumir que, se você está lendo este artigo, é porque já trabalha com o Hibernate e agora precisa fazer um relacionamento entre as suas tabelas. Então, parte da configuração do framework, ou explicação dos métodos serão omitidos - qualquer dúvida consulte artigos anteriores que publiquei no iMasters e veja como ter o ambiente funcionando.
A classe DAO nos códigos é quem possui o trabalho de persistência, mas ela não é requerida para o que vamos fazer neste artigo, pois você pode obter o begin(), save(), commit() etc do Hibernate por diversas formas.
 É preciso ter o Hibernate 3.x e o MySql 5.

OneToMany

O relacionamento OneToMany é bem usado e são poucas as vezes que de fato não precisamos tê-lo. Acredite, se não precisou até hoje, espere mais um pouco que essa necessidade vai aparecer. Vamos tirar a vantagem dos Annotations e veremos @OneToMany e @ManyToOne, ao invés dos .hbm. Como exemplo, existem vários cenários para exemplificar esse tipo de relacionamento, tais como: um time de futebol tem vários jogadores e uma infraestrutura tem vários servidores; porém, um jogador só pode jogar em um time (ou não. Depende da regra de negócio, e esse é segredo!), e um servidor está em uma infraestrutura.
Note: Há casos que um jogador joga em mais de um time, então temos o ManyToMany.
Para criar esse tipo de relacionamento, temos que identificar o ponto chave do relacionamento entre as classes. Para um time de futebol, por exemplo, temos que saber que há uma lista dos jogadores que pertencem ao clube, uma vez que um time pode ter de 0 a X jogadores (mesmo sem jogadores ele pode ser considerado um time de futebol, mas está sem dinheiro e demitiu todos os jogadores). Eu costumo chamar de HAS-AN List something (tem uma lista de alguma coisa).
A seguir, temos a class bean que representa o Team (por boas práticas, ela não deveria fazer o extends DAO, porém fiz aqui para facilitar e trazer sentindo às invocações do Hibernate que temos no code).
@Entity
public class Team extends DAO{
 @Id
 @GeneratedValue
 private long id;
 @Column
 private String nameTeam;
 private List<Player> players;

Usando @OneToMany

Agora vamos usar o relacionamento apropriado para a classe. A seguir, temos o code atualizado:
@Entity
public class Team  {
 private String nameTeam;
 @OneToMany(mappedBy = "team", targetEntity = Player.class, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
 private List<Player> players;
  • MappedBy: informamos o nome da variável de instância que vai indicar a quem aquele One pertence, ou seja, um jogador; e ele deve dizer a qual time este está associado;
  • TargetEntity: informa qual a entidade estamos associando;
  • FetchType.Lazy: foi escolhido por performace;
  • cascade: ALL para permitir alterações em todos os relacionamentos.
Pronto, agora já podemos dizer que o TEAM tem muitos jogadores (uma lista ).

Usando @ManyToOne

Na classe que representa o MANY (do manyToOne), que nesse caso é a Player, teremos uma anotação @ManyToOne na variável de instância que representa o TEAM.
@Entity
public class Player {
 @Id
 @GeneratedValue
 private long id;
 private String nickName; 
 @ManyToOne
 @JoinColumn(name="team_id")
 private Team team;
@JoinColumn: informamos o nome que terá o FK.
Ao rodar o código main na class Team:
public static void main(String args[]) {
  Team team1 = new Team();  
  team1.setNameTeam("São Paulo"); 
  
  Player jogador1 = new Player();
  Player jogador2 = new Player();
  
  jogador1.setNickName("Rogerio Ceni");
  jogador2.setNickName("Luiz Fabiano");

  // has-an associando o jogador ao team
  jogador1.setTeam(team1);
  jogador2.setTeam(team1);

  begin();
   getSession().save(team1);
   getSession().save(player1);
   getSession().save(player2);  
  commit();
 }
Talvez você tenha pensado que apenas um save() seria necessário, mas não é; pois precisamos colocar a instância dos players com a session, para que este se torne um objeto persistente. Do contrário, o Hibernate não tem o poder de persistir no banco. O resultado:
O team do São Paulo tem dois jogadores. Observe que o ID do team aparece na table do Player(team_id). Assim, sabemos a qual time este pertence.

 Erros comuns durante a programação:

  • Esquecer de associar as instâncias envolvidas no relacionamento. Se eu esquecer de dizer a qual team um jogador pertence, não teremos o resultado esperado, e o resultado na sua tabela será NULL, caso seja permitido esse valor na coluna;
  • Não salvar as instâncias que serão persistidas é outro erro comum. Quem está fazendo pela primeira vez acredita que dar um save apenas na classe  que representa o One (team) é o suficiente e por alguma mágica o Hibernate vai saber quais as outras instâncias devem ser persistidas. Aí vem a pergunta: como o Hibernate vai saber se você não transformou o “objeto java”, criando em um objeto-persistent?
Espero que tenham gostado do artigo. Até a próxima!
Obrigado pelo seu comentário

Postagens Relacionadas

Related Posts Plugin for WordPress, Blogger...

Programador GB