DEV Community

Samuel Luiz
Samuel Luiz

Posted on • Updated on

JPA Cheatsheet: visualizando relacionamentos

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;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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<>();
Enter fullscreen mode Exit fullscreen mode

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<>();
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Na classe Perfil, declaramos o atributo usuario com as anotações:

@OneToOne
@JoinColumn(name = "usuario_id")
private Usuario usuario;
Enter fullscreen mode Exit fullscreen mode

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)