OneToMany com Hibernate JPA

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!!! 🙂

7 comentários em “OneToMany com Hibernate JPA”

  1. Muito bom o post…

    Ajudou muito a aprender a usar o mapeamento de entidades.

    Parabéns pelo blog.

  2. 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 ??

    1. Antonio,
      com as novas algumas coisas mudaram sim, dai é preciso ver na documentacao como atualizar.
      abracos,

    2. 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,

  3. segui seu tutorial mais vendo a relacao criada pelo phpmyadmin está ON DELETE RESTRICT ON UPDATE RESTRICT como fazer para ficar cascade?

    1. Jefferson,

      Vc pode fazer isso no banco ou na anotação, veja que tem o atributo cascade.

      flw.

Deixe um comentário

O seu endereço de e-mail não será publicado.