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

Desafio

Segui as etapas do desafio e ao decorrer dele me deu o erro de um mesmo colega: [Dúvida] Erro: (.TransientObjectException: persistent instance references an unsaved transient instance)

Após achar que era problema no ManyToMany acabei fazendo a classe associativa de produto-pedido manualmente com cardinalidade One

Consegui entender melhor popular com dados as entidades e também adicionei no método principal

repositoryPedido_produto.deleteAll();
        repositoryPedido.deleteAll();
        repositoryProduto.deleteAll();
        repositoryCategoria.deleteAll();
        repositoryFornecedor.deleteAll();

Para que não criasse novamente elementos repetitivos e sempre fosse uma nova instância no BD

No final está tudo funcionando bem.

Porém um pouco diferente da opinão do instrutor:

Método Principal(Diferenças):

System.out.println("\nCategoria e produtos");

        repositoryCategoria.findAll().forEach(categoria -> {
            System.out.println("\nCategoria: " + categoria.getNome());

            categoria.getListaProdutos().forEach(prod -> {
                String nomeProduto = produto.getNome();
                String nomeFornecedor = prod.getFornecedor() != null
                        ? prod.getFornecedor().getNome()
                        : "Fornecedor não informado";

                System.out.println("Produto: " + nomeProduto + " | Fornecedor: " + nomeFornecedor);
            });
        });


        // Associando pedidos e produtos

        Pedido pedido1 = new Pedido(LocalDate.now());
        Pedido pedido2 = new Pedido(LocalDate.now());
        Pedido pedido3 = new Pedido(LocalDate.now());

        repositoryPedido.save(pedido1);
        repositoryPedido.save(pedido2);
        repositoryPedido.save(pedido3);

        Pedido_Produto pp1 = new Pedido_Produto(pedido1, produto);
        Pedido_Produto pp2 = new Pedido_Produto(pedido1, produto3);
        Pedido_Produto pp3 = new Pedido_Produto(pedido2, produto);
        Pedido_Produto pp4 = new Pedido_Produto(pedido2, produto2);
        Pedido_Produto pp5 = new Pedido_Produto(pedido2, produto1);
        Pedido_Produto pp6 = new Pedido_Produto(pedido3, produto1);

        repositoryPedido_produto.saveAll(List.of(pp1, pp2, pp3, pp4, pp5, pp6));

Classe associativa:

package Exercicios.GerenciadorDeProdutos.Principal;

import jakarta.persistence.*;

@Entity
public class Pedido_Produto {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "pedido_id")
    private Pedido pedido;

    @ManyToOne
    @JoinColumn(name = "produto_id")
    private Produto produto;

    private String nomeProduto;

    private Double preco;

    private String categoria;

    public Pedido_Produto(Pedido pedido, Produto produto) {
        this.pedido = pedido;
        this.produto = produto;
        this.nomeProduto = produto.getNome();

        if (produto.getCategorias() != null) {
            this.categoria = produto.getCategorias().getNome();
        }
    }

    public Pedido_Produto(){}

    public String getNomeProduto() {
        return nomeProduto;
    }

    public void setNomeProduto(String nomeProduto) {
        this.nomeProduto = nomeProduto;
    }

    public Long getId() {
        return id;
    }

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

    public Pedido getPedido() {
        return pedido;
    }

    public void setPedido(Pedido pedido) {
        this.pedido = pedido;
    }

    public Produto getProduto() {
        return produto;
    }

    public void setProduto(Produto produto) {
        this.produto = produto;
    }
}

mapeamento classe Produto

Mapeamento classe pedido

Independente de ter rodado e aparecido tudo no BD a minha lógica e maneira de fazer foi certa? Cometi alguma má pratica?

1 resposta
solução!

Olá Diego! Tudo bem?

Pelo que você descreveu, parece que você conseguiu contornar o problema de forma eficaz, mas há alguns pontos que podem ser ajustados para seguir boas práticas.

  1. TransientObjectException: Esse erro geralmente ocorre quando você tenta salvar uma entidade que possui referências a outras entidades que ainda não foram persistidas. Para evitar isso, certifique-se de salvar todas as entidades dependentes antes de associá-las.

  2. Classe Associativa: Criar uma classe associativa como Pedido_Produto é uma abordagem válida, especialmente quando você precisa armazenar informações adicionais sobre a associação. No entanto, se não houver necessidade de informações extras, um relacionamento @ManyToMany direto pode ser mais simples.

  3. CascadeType: Você está usando CascadeType.ALL em alguns relacionamentos. Isso pode ser útil, mas é importante entender que ele propaga todas as operações (persist, merge, remove, refresh, detach) para as entidades relacionadas. Use com cuidado para evitar exclusões não intencionais.

  4. Nome dos Atributos: No construtor de Pedido_Produto, você está atribuindo produto.getNome() a this.nomeProduto. Isso é redundante se você já tem a referência ao Produto. Considere acessar o nome diretamente do produto quando necessário.

  5. Limpeza do Banco de Dados: A abordagem de deletar todas as entidades antes de inserir novas é válida para testes, mas em um ambiente de produção, você deve ser mais seletivo para evitar perda de dados.

  6. Validação de Dados: Sempre que possível, verifique se as entidades que você está salvando estão completas e válidas para evitar inconsistências no banco de dados.

No geral, sua lógica está correta e funcional. Apenas certifique-se de entender as implicações de cada decisão, especialmente em relação a operações em cascata e persistência de entidades relacionadas.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.