Modelar e descrever relações entre entidades pode ser uma dificuldade para desenvolvedores iniciantes, mas no caso do JPA pode virar uma completa bagunça se não prestar a devida atenção. Quando aprendi esta tecnologia criei um pequeno guia pra me ajudar e me baseio nele até hoje quando estou com alguma dúvida.
OneToMany ou ManyToOne relationship
Regra: geralmente, o lado “many” é o dono da relação.
Exemplo: Cliente
e Pedido
.
Perguntas a se fazer:
- Um cliente pode ter quantos pedidos?
- Um pedido pode pertencer a quantos clientes?
- Eu preciso saber quais os pedidos do cliente?
- Eu preciso saber qual o cliente de cada pedido?
- Quem é o dono do relacionamento?
Respostas:
- [x] Um cliente pode ter vários pedidos. (OneToMany)
- [x] Um pedido pode pertencer a apenas um cliente. (ManyToOne)
- [x] Eu não preciso saber os pedidos de cada cliente, mas preciso saber o cliente de cada pedido. (Unidirecional)
- [x] O pedido é o dono do relacionamento.
Portanto, chegamos a conclusão de que um cliente pode ter vários pedidos, mas um pedido pertence a apenas um cliente.
Na classe pedido, nós declaramos o atributo cliente com as anotações:
-
@ManyToOne
(pois vários pedidos (Many) podem ter apenas um cliente (ToOne) -
@JoinColumn(name = “cliente_id”)
para criar uma coluna no banco de dados com o id do cliente
Classe Pedido:
@ManyToOne
@JoinColumn(name = “cliente_id”)
private Cliente cliente;
Na classe cliente, nós declaramos e INSTANCIAMOS uma coleção de pedidos com as anotações:
@JsonIgnore
(para a resposta em json da requisição HTTP ignorar esta lista e não criar um loop de pedidos com cliente e cliente com pedidos, gerando stack overflow, afinal nós não precisamos saber os itens). Uma alternativa ao JsonIgnore pode ser usar DTO’s.@OneToMany(mappedBy = “cliente”)
pois um cliente (One) pode ter vários pedidos (ToMany), o parâmetro mappedBy serve para mapear o atributo da classe Pedido (deve ser exatamente igual ao atributo declarado na classe)
Classe Cliente:
@OneToMany(mappedBy = “cliente”)
private List<Pedido> pedidos;
ManyToMany relationship
Exemplo: Um produto pode pertencer a várias categorias, e uma categoria possui vários produtos.
Perguntas a se fazer:
- Um produto pode pertencer a quantas categorias?
- Uma categoria pode possuir quantos produtos?
- Eu preciso saber quais produtos uma categoria possui?
- Eu preciso saber a quais categorias um produto pertence?
- Quem é o dono do relacionamento?
Respostas:
- [x] Um produto pode pertencer a varias categorias. (ManyToMany)
- [x] Uma categoria pode possuir vários produtos. (ManyToMany)
- [x] Eu preciso saber quais produtos uma categoria possui, e também saber a quais categorias um produto pertence. (Bidirecional)
- [x] O produto é o dono do relacionamento.
Portanto, chegamos a conclusão de que um produto pode pertencer a várias categorias, e uma categoria pode possuir vários produtos. Nesse caso, devemos criar uma tabela de associação usando o @JoinTable. Como o Produto possui essa anotação, é implícito que o Produto é o dono da relação.
Na classe produto, declaramos e INSTANCIAMOS uma coleção de categorias com as anotações:
-
@ManyToMany
(pois vários produtos (Many) podem ser de várias categorias (ToMany) -
@JoinTable
(para criar uma nova tabela) -
@JoinColumn
(dentro do @JoinTable para criar as colunas)
Classe Produto:
@ManyToMany
@JoinTable(name = "tb_product_category",
joinColumns = @JoinColumn(name = "product_id"),
inverseJoinColumns = @JoinColumn(name = "category_id"))
private Set<Category> categories = new HashSet<>();
Na classe category, declaramos e INSTANCIAMOS uma coleção de produtos com as anotações:
-
@ManyToMany(mappedBy = “categories”)
para mapear a coleção de categorias da classe Produto e indicar que o dono do relacionamento é o Produto.
Classe Categoria:
@ManyToMany(mappedBy = "categories")
private Set<Product> products = new HashSet<>();
OneToOne relationship
Exemplo: Um usuário pode ter um perfil associado, e um perfil pertence a apenas um usuário.
Perguntas a se fazer:
- Um usuário pode ter quantos perfis?
- Um perfil pode pertencer a quantos usuários?
- Eu preciso saber o perfil de cada usuário?
- Eu preciso saber o usuário associado a cada perfil?
- Quem é o dono do relacionamento?
Respostas:
- [x] Um usuário pode ter apenas um perfil. (OneToOne)
- [x] Um perfil pode pertencer a apenas um usuário. (OneToOne)
- [x] Eu preciso saber o perfil de cada usuário, e também o usuário associado a cada perfil. (Bidirecional)
- [x] O usuário é o dono do relacionamento.
Portanto, concluímos que um usuário pode ter apenas um perfil, e um perfil pertence a apenas um usuário. Nesse caso, o usuário será o dono do relacionamento.
Na classe Usuario
, declaramos o atributo perfil
com as anotações:
@OneToOne(mappedBy = "usuario")
private Perfil perfil;
Na classe Perfil
, declaramos o atributo usuario
com as anotações:
@OneToOne
@JoinColumn(name = "usuario_id")
private Usuario usuario;
Observe que a anotação @OneToOne
é utilizada em ambas as classes para indicar a relação One-To-One. A classe Perfil
possui a anotação @JoinColumn
para criar uma coluna no banco de dados com o id
do usuário, que será usado para mapear o relacionamento. A classe Usuario
utiliza a anotação mappedBy
no atributo perfil
para indicar que o relacionamento é mapeado pelo atributo usuario
na classe Perfil
.
Dessa forma, temos uma relação One-To-One entre Usuario
e Perfil
, em que um usuário pode ter apenas um perfil e um perfil pertence a apenas um usuário.
Top comments (0)