Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

[Dúvida] Migration e ampliação do projeto

Estou tentando ampliar esse projeto e decidi criar as classes Produto e Categoria, porém, não consegui desenvolver uma migration para poder criar as tabelas no banco de dados.

Posso criar uma única nova Migration para gerar as duas tabelas de uma vez? Se não, tendo que criar duas novas Miogrations, posso fazer isso de uma vez só, criando dois arquivos de uma vez? Seria possível me ajudar a implementar essas Migrations? Já tentei várias formas e pesquisas.

Ps: Criei os getter, setters e construtores porque o Lombok as vezes dá problema.

Classe Produto:

package br.com.mercadoapp.mercadoapp.model;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
@Table(name = "produtos")
public class Produto implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(max = 100)
    private String nome;

    @NotNull
    @Size(max = 500)
    private String Descricao;
    private Double preco;
    //private String imgUrl;

    private Set<Categoria> categorias = new HashSet<>();

    public Produto() {
    }

    public Produto(Long id, String nome, String descricao, Double preco) {
        this.id = id;
        this.nome = nome;
        Descricao = descricao;
        this.preco = preco;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getDescricao() {
        return Descricao;
    }

    public void setDescricao(String descricao) {
        Descricao = descricao;
    }

    public Double getPreco() {
        return preco;
    }

    public void setPreco(Double preco) {
        this.preco = preco;
    }

    public Set<Categoria> getCategorias() {
        return categorias;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Produto produto = (Produto) o;
        return Objects.equals(id, produto.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }
}

Classe Categoria

package br.com.mercadoapp.mercadoapp.model;

import jakarta.persistence.*;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
@Table(name = "categorias")
public class Categoria implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nomeCategoria;

    //Conjunto de produtos
    private Set<Produto> produtos = new HashSet<>();

    public Categoria() {
    }

    public Categoria(Long id, String nomeCategoria) {
        this.id = id;
        this.nomeCategoria = nomeCategoria;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNomeCategoria() {
        return nomeCategoria;
    }

    public void setNomeCategoria(String nomeCategoria) {
        this.nomeCategoria = nomeCategoria;
    }

    public Set<Produto> getProdutos() {
        return produtos;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || getClass() != o.getClass()) return false;
        Categoria categoria = (Categoria) o;
        return Objects.equals(id, categoria.id);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(id);
    }
}
1 resposta
solução!

Olá!

1. Pode criar uma única migration para as duas tabelas? Sim, pode! O Flyway (ou outro framework de migration, como Liquibase) permite que você crie uma única migration SQL ou Java que adicione quantas tabelas quiser de uma vez.

2. Pode criar duas migrations separadas? Também pode! Basta que cada arquivo siga a ordem correta de versão (V1__, V2__, etc.) e que as dependências entre as tabelas sejam respeitadas (por exemplo, se uma tiver FK para a outra, ela deve vir depois).

3. Pode criar dois arquivos de migration de uma vez? Pode, desde que os nomes sigam a ordem numérica correta: V2__create_categoria.sql, depois V3__create_produto.sql (ou vice-versa).

Correções e melhorias nas entidades

Você esqueceu de mapear os relacionamentos entre Produto e Categoria. Se eles têm uma relação muitos-para-muitos, você precisa declarar isso com JPA corretamente.

Produto.java

@ManyToMany
@JoinTable(name = "produto_categoria",
    joinColumns = @JoinColumn(name = "produto_id"),
    inverseJoinColumns = @JoinColumn(name = "categoria_id"))
private Set<Categoria> categorias = new HashSet<>();

Categoria.java

@ManyToMany(mappedBy = "categorias")
private Set<Produto> produtos = new HashSet<>();

Exemplo de migration SQL única (Flyway)

Se quiser fazer uma única migration SQL (V2__create_produto_e_categoria.sql), ficaria assim:

CREATE TABLE categorias (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    nome_categoria VARCHAR(255) NOT NULL
);

CREATE TABLE produtos (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    nome VARCHAR(100) NOT NULL,
    descricao VARCHAR(500) NOT NULL,
    preco DOUBLE
);

CREATE TABLE produto_categoria (
    produto_id BIGINT NOT NULL,
    categoria_id BIGINT NOT NULL,
    PRIMARY KEY (produto_id, categoria_id),
    FOREIGN KEY (produto_id) REFERENCES produtos(id),
    FOREIGN KEY (categoria_id) REFERENCES categorias(id)
);

Coloque esse arquivo na pasta de migrations (geralmente src/main/resources/db/migration) e o Flyway aplicará automaticamente ao subir a aplicação.