EXISTE UMA NOVA VERSÃO DESSE POST.
CLICK AQUI: http://uaihebert.com/?p=1622&page=20
Olá, bom dia.
Vamos ver hoje o relacionamento @OneToMany e @ManyToOne Unidirecional e Bidirecional.
Podemos fazer o relacionamento @OneToMany de dois modos, utilizando a anotação @JoinColumn ou a anotação @JoinTable.
Irei utilizar o código de posts passados. Se você quiser montar um ambiente para executar o código do post, você pode olhar os outros posts sobre o assunto: @OneToOne Unidirecional e Bidirecional, Mapeando Duas Tabelas em uma Classe, Mapeando Datas (Date) e Enum, Chave Primária Composta, SequenceGenerator, TableGenerator – Chave Primária Simples, Auto Create Schema Script com: Ant, Hibernate 3 e JPA 2, Tutorial Hibernate 3 com JPA 2.
Vou utilizar um simples exemplo, um Customer (cliente) pode ter vários cachorros, mas um Dog (cachorro) só pode ter um Customer.
Vamos ao código da classe Dog:
package com;
//Using the * to make the import list smaller
import javax.persistence.*;
@Entity
@Table(name="DOG")
@SequenceGenerator(name="DOG_SEQUENCE", sequenceName="DOG_SEQUENCE", allocationSize=1, initialValue=0)
public class Dog {
public Dog(){
}
public Dog(String name){
this.name = name;
}
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="DOG_SEQUENCE")
private int id;
@Column
private String name;
//Getters and Setters
}
Repare que como nosso código é Unidirecional ele não faz menção do Customer.
Vamos ver agora, como ficará nossa classe Customer utilizando o @JoinTable:
package com;
import java.util.List;
//Using the * to make the import list smaller
import javax.persistence.*;
@Entity
@Table(name = "CUSTOMER")
@SequenceGenerator(name = "CUSTOMER_SEQUENCE", sequenceName = "CUSTOMER_SEQUENCE", allocationSize = 1, initialValue = 0)
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CUSTOMER_SEQUENCE")
private int id;
@Column
private String name;
@OneToOne(cascade = CascadeType.ALL, optional = true, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name="USER_ID", nullable=true)
private User user;
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinTable(name="CUSTOMER_HAS_DOGS", joinColumns={@JoinColumn(name="CUSTOMER_ID", referencedColumnName="id")}, inverseJoinColumns={@JoinColumn(name="DOG_ID", referencedColumnName="id")})
private List dogs;
//Getters and Setters
}
A anotação @JoinTable é bem simples e seu uso bem prático:
- “name” – indica qual será a tabela que realizará a junção entre Customer e Dog (Por padrão colocamos o lado dominante como primeiro nome na tabela).
- “joinColumns” – informa ao JPA um conjunto de chaves (um array separado por vírgulas) a ser utilizado para se identificar um registro. Poderia ser, por exemplo, o ID e o nome (“name”).
- “@JoinColumn” – aponta uma coluna que servirá de chave primária na tabela de relacionamento. “name” é o nome que a coluna da tabela terá, e “referencedColumnName” é a chave primária da tabela dona do relacionamento; em nosso caso utilizamos id da tabela Customer. (Ao final do post veremos o real lado dominante desse relacionamento. Utilizo o Customer apenas para ficar didaticamente mais fácil)
- “inverseJoinColumns” – faz o mapeamento das colunas da tabela do lado “dominado/fraco”.
Vamos inserir as informações no banco de dados? Abaixo o código que irá criar um relacionamento de um Customer com Dog (para configurar sua aplicação, verifique os links no começo do post e siga os passos):
package com;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("Hello");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
List dogs = new ArrayList();
dogs.add(new Dog("Terminator"));
dogs.add(new Dog("Fluffy"));
dogs.add(new Dog("Bacon"));
Customer customer = new Customer();
customer.setName("Arnold");
customer.setDogs(dogs);
em.persist(customer);
em.getTransaction().commit();
}
catch (Exception e) {
em.getTransaction().rollback();
e.printStackTrace();
}
finally{
emf.close();
}
System.out.println("It is over");
}
}
Olhe os resultados:
Imagem Console.
Imagem banco de dados.
O JPA buscou o valor da sequence para cada objeto a ser inserido, inseriu cada registro na tabela, e depois fez o relacionamento na tabela “CUSTOMER_HAS_DOGS”.
Para utilizar o mapeamento @OneToMany sem uma tabela adicional, basta utilizar a anotação @JoinColumn ao invés de @JoinTable. Veja como nossa classe Customer ficará:
package com;
import java.util.List;
//Using the * to make the import list smaller
import javax.persistence.*;
@Entity
@Table(name = "CUSTOMER")
@SequenceGenerator(name = "CUSTOMER_SEQUENCE", sequenceName = "CUSTOMER_SEQUENCE", allocationSize = 1, initialValue = 0)
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CUSTOMER_SEQUENCE")
private int id;
@Column
private String name;
@OneToOne(cascade = CascadeType.ALL, optional = true, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name="USER_ID", nullable=true)
private User user;
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUSTOMER_ID")
private List dogs;
//Getters and Setters
}
Agora a anotação @JoinColumn indica qual será a coluna utilizada para identificação.
Apague o SCHEMA do database antigo, crie novamente e veja o resultado após executar a classe Main:
Imagem do Console.
Imagem do banco de dados.
Veja que agora não existe mais uma tabela entre Customer e Dog. Na tabela Dog, foi criado uma coluna que fará essa referência.
E para tornar nosso relacionamento Bidirecional, vamos alterar a classe Dog:
package com;
//Using the * to make the import list smaller
import javax.persistence.*;
@Entity
@Table(name="DOG")
@SequenceGenerator(name="DOG_SEQUENCE", sequenceName="DOG_SEQUENCE", allocationSize=1, initialValue=0)
public class Dog {
public Dog(){
}
public Dog(String name){
this.name = name;
}
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="DOG_SEQUENCE")
private int id;
@Column
private String name;
@ManyToOne(cascade=CascadeType.ALL)
private Customer owner;
//Getters and Setters
}
A explicação da diferença entre Unidirecional e Bidirecional você encontra aqui: @OneToOne Unidirecional e Bidirecional.
Por padrão, a anotação @ManyToOne deve ser a dominante no relacionamento com @OneToMany. Você poderá notar que não existe a opção “mappedBy” para na anotação @ManyToOne, mas na anotação @OneToMany existe.
Para praticar, você poderia passar todas as configurações para a anotação @ManyToOne e colocar o parâmetro mappedBy em @OneToMany.
Espero que o post te hoje possa te ajudar.
Dúvida/Sugestão basta postar.
Até a próxima.

