Opa! Pessoal,
O post de hoje vou apresentar como criar o relacionamento oneToMany / ManyToOne de forma simples. Quem ai 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. Estarei apenas focando em como definir os relacionamentos à nível de código e para isso teremos code apenas para o objetivo do post. Quero evitar posts grandes sem necessidade.
lets go…
Required
– Vou assumir que se você está lendo este post é pq já está brincando com o Hibernate e agora precisa fazer um relacionamento entre as suas tabelas, então parte de configuração do framework, ou explicação dos métodos serão omitidos, qualquer dúvida consulte outros posts no blog na categoria Hibernate, e veja como ter o ambiente funcionando.
– A classe DAO nos códigos é que possui o trabalho de persistência, ela não é requirida para o post, pois vc uma vez que podemos obter o begin(), save(), commit() etc do hibernate por diversas formas.
– Hibernate 3.x
– MySql 5
OneToMany
O relacionamento OneToMany é bem usado, e são poucas vezes que de fato não precisamos te-lo, então é aquele lance se não precisou até hoje, espere mais um pouco que essa necessidade vai nascer. Vamos tirar a vantagem dos annotations e veremos @OneToMany e @ManyToOne ao invés dos .hbm, Como exemplo há vários cenários para exemplificar este tipo de relacionamento, tais como: um time de futebol tem vários jogadores, uma infra-estrutura tem vários servidores, porém um jogador só pode jogar em um time(ou não depende da regra de negócio, aqui está o pulo do gato), e um servidor está em uma infra-estrutura.
Note: Há casos que um jogador joga mais de um time, daí temos o ManyToMany.
Para criar esse tipo de relacionamento temos que identificar o ponto chave do relacionamento entre as classes, como por exemplo, para um Time de futebol, temos que saber que há uma lista com os jogadores que pertencem ao clube, uma vez que um team não tem apenas 1 jogador este pode ter de 0..X(mesmo sem jogadores ele pode ser considerado um team de futebol, mas está sem grana 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 elas não deveria extends DAO, porém fiz aqui para ser mais pratico e fazer sentindo com as 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 variavel de instância que vai indicar a quem aquele One pertence, ou seja, um jogador 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, já dizemos que um 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 variavel de instancia 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 1 (um) save() seria necessario, mas não é, pois precisamos colocar a instancia dos players com a session, para que este se torne um objeto persistente do contrario, o Hibernate não 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 fato comum, quem está fazendo pela primeira acredita que dar um save apenas na classe que representar One (team), é o sufuciente e por alguma mágina o Hibernate vai saber quais outras instancias devem ser persistidas, ai 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 post, vou ficando por aqui.
Abracos see you next post!!! 🙂
Muito bom o post…
Ajudou muito a aprender a usar o mapeamento de entidades.
Parabéns pelo blog.
você já tentou usar as libs novas disponíveis no site do hibernate??
tenta usar porque eu tentei e dava muito conflito e tive que deixar tudo na vesão 3 mesmo tendo a 4 disponivel
Gostaria de levantar uma duvida que tenho
Hibernate é melhor porque?
pergunto isso porque quando configurei o hibernate tive que colocar varias dependências para funcionar o Annotations
além de api de log4 etc..
sem contar que quando quiz atualizar as libs fui no sites baixei todas as mais novas atualizações e dava problema de versão,
hibernate cor 4 não funciona com Annotations 3 coisas desse tipo, sendo assim tive que dar o braço a torcer e deixar tudo va versão 3 pra funcionar direito (essa foi uma impressão que eu tive pode ser que eu estava fazendo coisa erra, mas aparentemente hibernate para configurara parece complicado )
e quando utilizei o OpenJPA só adicionei no meu path uma (1) lib e pronto, Annotations funcionando e os gets, set , commit e engenharia reversa funcionando, bem simples
alguém poderia dizer pontos positivos e negativos do hibernate e openjpa??
já vou começar
hibernate
positivo:
Grandes empresas usam.
tem muitos filtros.
Usado em grandes projetos
muita documentação (para marinheiro de primeira viagem um pouco complicado)
negativos:
Muitas dependências
as dependências podem dar conflitos
no meu caso tive que deixar a versão antiga por causa dos conflitos
acredito que seja mais pesado em tamanho e pocessamento por ter muitas libs
openjpa
positivos:
tudo esta encapsulado em um jar
não tem muitas dependências
rápida configuração
parece ser bem rapidinho (Não fiz testes de performance para verificar isso , só insert e delete update simples)
pela simplicidade acredito que pode ser usado em pequenos projetos sem medo porque ele usa jpa
negativos:
pouca documentação
não é muito divulgado
não conheço projetos que usam ele
alguém poderia continuar ??
Antonio,
com as novas algumas coisas mudaram sim, dai é preciso ver na documentacao como atualizar.
abracos,
Antonio,
Entendo sua frustação como tudo há pontos positivos/negativos, mas normalmente a versao mais recente dá suporte a versao antiga o que acontece é de ser marcado como deprecated e a sua IDE ficar reclamando, mas o codigo vai rodar, passei por isso, quando atualizei as libs para a versao mais recente. Outro detalhe, ter mais ou menos lib n afeta em nada de performance até hj n vi ter problemas de desempenho pq tinha 10 ou 20 libs e para gerenciar libs na melhor que um ant ou maven da vida que permite fazer um bom gerenciamento e bem organizado. Entao vc pode ter arquivos do hibernate 3 e 4 e dizer o que cada projeto vai usar. Sobre a vantagem do Hibernate uma é por ser forte na comunidade n por questao de mkt, é pq o framework é bom de verdade em termo de performance, documentação, alta curva de aprendizado. E em solucoes criticas que não é um CRUD ele n ti deixa na mão. Quem usa framework de persistencia so para crud eu concordo com vc que as vezes há outros mostram vantagens sobre o hibernate em alguns aspectos. Porém, qdo a coisa é critica poucos conseguem dá conta do tranco. E sobre o log4j, n é preciso configurar para o hibernate funciona, é opcional. O openjpa usei poucas vezes e em nada critico.
abracos,
segui seu tutorial mais vendo a relacao criada pelo phpmyadmin está ON DELETE RESTRICT ON UPDATE RESTRICT como fazer para ficar cascade?
Jefferson,
Vc pode fazer isso no banco ou na anotação, veja que tem o atributo cascade.
flw.
me add no msn ai podemos ja ver isso
j3ff3rs0n_7@hotmail.com