1
resposta

[Dúvida] Erro: (InvalidDataAccessApiUsageException: detached entity passed to persist)

Estou tendo esse erro todas as vezes que tento executor meu código (org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.example.demo.model.Categoria), alguém sabe aonde está o erro?

@Component
public class Principal {

    @Autowired
    ProdutoRepository produtoRepository;
    @Autowired
    PedidoRepository pedidoRepository;
    @Autowired
    CategoriaRepository categoriaRepository;
    @Autowired
    FornecedorRepository fornecedorRepository;
  
    public void executar() {
        // Criando categorias
        Categoria categoriaEletronicos = new Categoria("Eletrônicos");
        Categoria categoriaLivros = new Categoria("Livros");
        categoriaRepository.saveAll(List.of(categoriaEletronicos, categoriaLivros));

        // Criando fornecedores
        Fornecedor fornecedorTech = new Fornecedor("Tech Supplier");
        Fornecedor fornecedorLivros = new Fornecedor("Livraria Global");
        fornecedorRepository.saveAll(List.of(fornecedorTech, fornecedorLivros));

        // Criando produtos e associando às categorias
        Produto produto1 = new Produto("Notebook", 3500.0, fornecedorTech);
        Produto produto2 = new Produto("Smartphone", 2500.0, fornecedorTech);
        Produto produto3 = new Produto("Livro de Java", 100.0, fornecedorLivros);
        Produto produto4 = new Produto("Livro de Spring Boot", 150.0, fornecedorLivros);

        // Associando produtos às categorias
        produto1.adicionarCategoria(categoriaEletronicos);
        produto2.adicionarCategoria(categoriaEletronicos);
        produto3.adicionarCategoria(categoriaLivros);
        produto4.adicionarCategoria(categoriaLivros);

        // Agora, salvar os produtos após associar corretamente
        produtoRepository.saveAll(List.of(produto1, produto2, produto3, produto4));

        // Criando pedidos
        Pedido pedido1 = new Pedido(LocalDate.now());
        Pedido pedido2 = new Pedido(LocalDate.now());

        // Adicionando produto a pedido
        pedido1.adicionarProduto(produto1);
        pedido2.adicionarProduto(produto2);

        pedidoRepository.saveAll(List.of(pedido1, pedido2));
    }
}

@Entity
public class Produto {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String nome;
    @Column(name = "valor", nullable = false)
    private Double preco;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "categoria_id")
    private Categoria categoria;

    @ManyToMany(mappedBy = "produtos", cascade = CascadeType.ALL)
    private List<Pedido> pedidos = new ArrayList<>();

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "fornecedor_id")
    private Fornecedor fornecedor;


    //métodos
    // verifica se  o pedido é nulo e se a lista ja não contem o pedido
    public void adicionarPedido(Pedido pedido) {
        if (pedido != null && !pedidos.contains(pedido)) {
            pedidos.add(pedido);
            pedido.adicionarProduto(this);
        } else {
            System.out.println("Pedido inválido ou já atribuído.");
        }
    }
    public void adicionarCategoria(Categoria categoria) {
        if (categoria != null && !categoria.equals(this.categoria)) {
            this.categoria = categoria;
            categoria.adicionarProduto(this); // Sincroniza bidirecionalmente
        } else {
            System.out.println("Categoria inválida ou já atribuída.");
        }
    }
    //construtor
    public Produto() {}
    public Produto(String nome, Double preco, Fornecedor fornecedor) {
        this.nome = nome;
        this.preco = preco;
        this.fornecedor = fornecedor;
    }
    public Produto(String nome, Double preco) {
        this.nome = nome;
        this.preco = preco;
    }

    //setters
    public void setNome(String nome) {
        this.nome = nome;
    }
    public void setPreco(Double preco) {
        this.preco = preco;
    }
    public void setCategoria(Categoria categoria) {
        this.categoria = categoria;
    }
    public void setPedidos(List<Pedido> pedidos) {
        this.pedidos = pedidos;
    }

    public void setFornecedor(Fornecedor fornecedor) {
        if (fornecedor!=null && !fornecedor.equals(this.fornecedor)){
            this.fornecedor = fornecedor;
        } else{
            System.out.println("Fornecedor inválido ou já atribuído.");
        }
    }

    //getters
    public Categoria getCategoria() {
        return categoria;
    }
    public Long getId() {
        return id;
    }
    public String getNome() {
        return nome;
    }
    public Double getPreco() {
        return preco;
    }
    public List<Pedido> getPedidos() {
        return pedidos;
    }
    public Fornecedor getFornecedor() {
        return fornecedor;
    }
}
1 resposta

Olá Luiz! Tudo bem?

Esse erro que você está enfrentando, InvalidDataAccessApiUsageException: detached entity passed to persist, geralmente ocorre quando uma entidade que não está mais sendo gerenciada pelo contexto de persistência é passada para ser salva ou atualizada.

No seu caso, o problema parece estar relacionado ao modo como você está gerenciando as entidades Categoria e Produto. Vamos dar uma olhada em algumas possíveis causas e soluções:

  1. Relacionamento entre Categoria e Produto: Pelo que você mencionou, o relacionamento entre Categoria e Produto deve ser bidirecional. No entanto, no código que você compartilhou, não vi a classe Categoria. Certifique-se de que a classe Categoria está configurada corretamente com a anotação @OneToMany para o relacionamento com Produto e que a lista de produtos está sendo inicializada corretamente.

    @Entity
    public class Categoria {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
        private String nome;
    
        @OneToMany(mappedBy = "categoria", cascade = CascadeType.ALL, orphanRemoval = true)
        private List<Produto> produtos = new ArrayList<>();
    
        // Construtores, getters e setters
    }
    
  2. Sincronização do Contexto de Persistência: Após salvar as categorias com categoriaRepository.saveAll(...), as instâncias de Categoria devem ser gerenciadas pelo contexto de persistência. Certifique-se de que, ao associar as categorias aos produtos, você está usando as instâncias retornadas pelo saveAll, que agora estão gerenciadas.

  3. Verifique o CascadeType: O CascadeType.ALL na associação @ManyToOne em Produto pode estar causando problemas se a entidade Categoria não estiver sendo gerenciada corretamente. Tente usar CascadeType.MERGE ou CascadeType.PERSIST, dependendo da sua necessidade.

  4. Persistência Bidirecional: Certifique-se de que, ao adicionar um produto a uma categoria, você também está adicionando a categoria ao produto, como parece que você já está fazendo com o método adicionarCategoria.

Se após essas verificações o problema persistir, você poderia compartilhar o seu projeto completo? Assim poderei fazer testes para identificar o problema.

Espero ter ajudado e bons estudos!

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