Seguindo os exercícios do projeto de "gerenciar-pedidos", tentei fazer algo um pouco diferente, ao fazer um menu assim como no "screen-match". Optei por não fazer a classe de Pedidos para evitar mais complicações.
Classe Main (tirei todos os imports e os metodos de cadastrar categoria e fornecedor)
package com.example.gerenciar_pedidos;
@SpringBootApplication
public class GerenciarPedidosApplication implements CommandLineRunner {
@Autowired
private ProdutoRepository produtoRepository;
@Autowired
private CategoriaRepository categoriaRepository;
@Autowired
private FornecedorRepository fornecedorRepository;
Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
SpringApplication.run(GerenciarPedidosApplication.class, args);
}
@Override
public void run(String... args) {
var opcao = -1;
while (opcao != 0) {
var menu = """
1 - Cadastrar categoria
2 - Cadastrar fornecedor
3 - Cadastrar produto
0 - Sair
""";
System.out.print(menu);
opcao = scanner.nextInt();
scanner.nextLine();
switch (opcao) {
case 1:
cadastrarCategoria();
break;
case 2:
cadastrarFornecedor();
break;
case 3:
cadastrarProduto();
break;
case 0:
System.out.println("Saindo...");
break;
default:
System.out.println("Opção inválida");
}
}
}
private void cadastrarProduto() {
System.out.println("\nProdutos já cadastrados: ");
List<Produto> produtoCadastrados = produtoRepository.findAll();
produtoCadastrados.forEach(System.out::println);
System.out.print("Digite o nome do produto: ");
String produtoUser = scanner.next();
System.out.print("Digite o preço: ");
var precoUser = scanner.nextDouble();
System.out.print("Digite a categoria associada: ");
var categoriaProduto = scanner.next();
Categoria categoriaAssociada = new Categoria(categoriaProduto);
Produto produto = new Produto(produtoUser, precoUser, categoriaAssociada);
produtoRepository.save(produto);
}
}
Classe Produto
package com.example.gerenciar_pedidos.model;
import jakarta.persistence.*;
@Entity
public class Produto {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String nome;
@Column(name = "valor")
private Double preco;
@ManyToOne
@JoinColumn(name = "categoria_id")
private Categoria categoria;
@Transient
@ManyToOne
@JoinColumn(name = "fornecedor_id")
private Fornecedor fornecedor;
public Produto(String nome, Double preco, Categoria categoria) {
this.nome = nome;
this.preco = preco;
this.categoria = categoria;
}
Erro
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: persistent instance references an unsaved transient instance of 'com.example.gerenciar_pedidos.model.Categoria' (save the transient instance before flushing)
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:368) ~[spring-orm-6.2.1.jar:6.2.1]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246) ~[spring-orm-6.2.1.jar:6.2.1]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566) ~[spring-orm-6.2.1.jar:6.2.1]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:795) ~[spring-tx-6.2.1.jar:6.2.1]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:758) ~[spring-tx-6.2.1.jar:6.2.1]
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:698) ~[spring-tx-6.2.1.jar:6.2.1]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:416) ~[spring-tx-6.2.1.jar:6.2.1]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.2.1.jar:6.2.1]
IMPORTANTE: A categoria cadastrada existe no banco de dados
O comportamento desejado é que os IDs fossem relacionados.